summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/2.6.18')
-rw-r--r--trunk/2.6.18/00000_README62
-rw-r--r--trunk/2.6.18/10002_xen-3.3.0.patch (renamed from trunk/2.6.18/10001_xen-3.2.0.patch)87479
-rw-r--r--trunk/2.6.18/30073_nfs-write-corruption.patch76
-rw-r--r--trunk/2.6.18/30074_x86-clear-df-before-calling-signal-handler.patch57
-rw-r--r--trunk/2.6.18/30075_3w-xxxx-bigmem-corruption.patch42
-rw-r--r--trunk/2.6.18/30076_dnotify-race-locking.patch29
-rw-r--r--trunk/2.6.18/30077_sctp-make-sure-n-sizeof-does-not-overflow.patch29
-rw-r--r--trunk/2.6.18/30078_esp-iv-in-linear-part-of-skb.patch48
-rw-r--r--trunk/2.6.18/30079a_amd64-fix-zeroing-on-exception-in-copy_user-pre.patch798
-rw-r--r--trunk/2.6.18/30079b_amd64-fix-zeroing-on-exception-in-copy_user.patch272
-rw-r--r--trunk/2.6.18/30080_tty-fix-for-tty-operations-bugs.patch183
-rw-r--r--trunk/2.6.18/30081_check-privileges-before-setting-mount-propagation.patch28
-rw-r--r--trunk/2.6.18/30082a_x86-add-copy_user_handle_tail.patch56
-rw-r--r--trunk/2.6.18/30082b_x86-fix-copy_user.patch537
-rw-r--r--trunk/2.6.18/30083_x86-wrong-register-was-used-in-align-macro.patch29
-rw-r--r--trunk/2.6.18/30084_cifs-fix-compiler-warning.patch21
-rw-r--r--trunk/2.6.18/30085_netfilter-nf_nat_snmp_basic-fix-range-check.patch27
-rw-r--r--trunk/2.6.18/30086_sound-ensure-device-number-is-valid-in-snd_seq_oss_synth_make_info.patch30
-rw-r--r--trunk/2.6.18/30087_vfs-fix-lookup-on-deleted-directory.patch71
19 files changed, 81334 insertions, 8540 deletions
diff --git a/trunk/2.6.18/00000_README b/trunk/2.6.18/00000_README
index 7ee89f7..c9c4c91 100644
--- a/trunk/2.6.18/00000_README
+++ b/trunk/2.6.18/00000_README
@@ -19,8 +19,8 @@ Numbering
Patches
-------
-10001_xen-3.2.0.patch
- Upstream 3.2.0 patch
+10002_xen-3.3.0.patch
+ Upstream 3.3.0 patch
30001_nfnetlink_log-null-deref.patch
[SECURITY] Fix remotely exploitable NULL pointer dereference in
@@ -329,6 +329,64 @@ Patches
heap overflow
See CVE-2008-1673
+30073_nfs-write-corruption.patch
+ Fix potential nfs write corruption (closes: #470719)
+
+30074_x86-clear-df-before-calling-signal-handler.patch
+ [i386/amd64] Clear DF before calling signal handler. (closes: #469058)
+ CVE-2008-1367
+
+30075_3w-xxxx-bigmem-corruption.patch
+ 3w-xxxx: Fix data corruption on em64t systems w/ > 2GB of memory
+ (closes: #464923).
+
+30076_dnotify-race-locking.patch
+ Add missing locking for the dnotify-race fix that was included in
+ the upstream commit
+
+30077_sctp-make-sure-n-sizeof-does-not-overflow.patch
+ [SECURITY] Fix potential overflow condition in
+ sctp_getsockopt_local_addrs_old
+ See CVE-2008-2826
+
+30078_esp-iv-in-linear-part-of-skb.patch
+ [SECURITY] Avoid tripping BUG() in IPsec code when the first fragment
+ of an ESP packet does not contain the entire ESP header and IV
+ See CVE-2007-6282
+
+30079a_amd64-fix-zeroing-on-exception-in-copy_user-pre.patch
+30079b_amd64-fix-zeroing-on-exception-in-copy_user.patch
+ [SECURITY] [amd64] Fix potential information leak when a copy
+ operation fails by properly zeroing out destination memory
+ See CVE-2008-2729
+
+30080_tty-fix-for-tty-operations-bugs.patch
+ [SECURITY] Fix issues with tty operation handling in various drivers
+ See CVE-2008-2812
+
+30081_check-privileges-before-setting-mount-propagation.patch
+ [SECURITY] Check CAP_SYS_ADMIN when changing mountpoint type
+ See CVE-2008-2931
+
+30082a_x86-add-copy_user_handle_tail.patch
+30082b_x86-fix-copy_user.patch
+ [SECURITY][amd64] Fix memory leak in the copy_user routine, see #490910.
+ See CVE-2008-0598
+
+30083_x86-wrong-register-was-used-in-align-macro.patch
+ Fix regression introduced upstream by the fix for CVE-2008-0598
+
+30084_cifs-fix-compiler-warning.patch
+30085_netfilter-nf_nat_snmp_basic-fix-range-check.patch
+ Fix regressions introduced upstream by the fixes for CVE-2008-1673
+
+30086_sound-ensure-device-number-is-valid-in-snd_seq_oss_synth_make_info.patch
+ Fix possible information leak in seq_oss_synth.c
+ See CVE-2008-3272
+
+30087_vfs-fix-lookup-on-deleted-directory.patch
+ Fix potential memory leak in lookup path
+ See CVE-2008-3275
50009_gentooify-tls-warning.patch
Change tls warning instructions to apply directly to Gentoo.
diff --git a/trunk/2.6.18/10001_xen-3.2.0.patch b/trunk/2.6.18/10002_xen-3.3.0.patch
index d3d6c2b..996125c 100644
--- a/trunk/2.6.18/10001_xen-3.2.0.patch
+++ b/trunk/2.6.18/10002_xen-3.3.0.patch
@@ -1,6 +1,32 @@
-diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kconfig
---- linux-2.6.18.8/arch/i386/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/Kconfig 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/boot/Makefile linux-2.6.18-xen-3.3.0/arch/i386/boot/Makefile
+--- linux-2.6.18.8/arch/i386/boot/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/boot/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -26,7 +26,7 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
+ #RAMDISK := -DRAMDISK=512
+
+ targets := vmlinux.bin bootsect bootsect.o \
+- setup setup.o zImage bzImage
++ setup setup.o zImage bzImage vmlinuz vmlinux-stripped
+ subdir- := compressed
+
+ hostprogs-y := tools/build
+@@ -133,5 +133,13 @@ zlilo: $(BOOTIMAGE)
+ cp System.map $(INSTALL_PATH)/
+ if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+
++$(obj)/vmlinuz: $(obj)/vmlinux-stripped FORCE
++ $(call if_changed,gzip)
++ @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
++
++$(obj)/vmlinux-stripped: OBJCOPYFLAGS := -g --strip-unneeded
++$(obj)/vmlinux-stripped: vmlinux FORCE
++ $(call if_changed,objcopy)
++
+ install:
+ sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
+diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.3.0/arch/i386/Kconfig
+--- linux-2.6.18.8/arch/i386/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/Kconfig 2008-08-21 11:36:07.000000000 +0200
@@ -16,6 +16,7 @@ config X86_32
config GENERIC_TIME
@@ -9,13 +35,14 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
default y
config LOCKDEP_SUPPORT
-@@ -103,6 +104,16 @@ config X86_PC
+@@ -103,6 +104,17 @@ config X86_PC
help
Choose this option if your computer is a standard PC or compatible.
+config X86_XEN
+ bool "Xen-compatible"
+ select XEN
++ select X86_PAE
+ select X86_UP_APIC if !SMP && XEN_PRIVILEGED_GUEST
+ select X86_UP_IOAPIC if !SMP && XEN_PRIVILEGED_GUEST
+ select SWIOTLB
@@ -26,7 +53,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
config X86_ELAN
bool "AMD Elan"
help
-@@ -213,6 +224,7 @@ source "arch/i386/Kconfig.cpu"
+@@ -213,6 +225,7 @@ source "arch/i386/Kconfig.cpu"
config HPET_TIMER
bool "HPET Timer Support"
@@ -34,7 +61,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
help
This enables the use of the HPET for the kernel's internal timer.
HPET is the next generation timer replacing legacy 8254s.
-@@ -263,7 +275,7 @@ source "kernel/Kconfig.preempt"
+@@ -263,7 +276,7 @@ source "kernel/Kconfig.preempt"
config X86_UP_APIC
bool "Local APIC support on uniprocessors"
@@ -43,7 +70,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
help
A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU
-@@ -288,12 +300,12 @@ config X86_UP_IOAPIC
+@@ -288,12 +301,12 @@ config X86_UP_IOAPIC
config X86_LOCAL_APIC
bool
@@ -58,7 +85,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
default y
config X86_VISWS_APIC
-@@ -303,7 +315,7 @@ config X86_VISWS_APIC
+@@ -303,7 +316,7 @@ config X86_VISWS_APIC
config X86_MCE
bool "Machine Check Exception"
@@ -67,7 +94,16 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
---help---
Machine Check Exception support allows the processor to notify the
kernel if it detects a problem (e.g. overheating, component failure).
-@@ -402,6 +414,7 @@ config X86_REBOOTFIXUPS
+@@ -384,7 +397,7 @@ config I8K
+
+ config X86_REBOOTFIXUPS
+ bool "Enable X86 board specific fixups for reboot"
+- depends on X86
++ depends on !X86_XEN
+ default n
+ ---help---
+ This enables chipset and/or board specific fixups to be done
+@@ -402,6 +415,7 @@ config X86_REBOOTFIXUPS
config MICROCODE
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
@@ -75,7 +111,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
---help---
If you say Y here and also to "/dev file system support" in the
'File systems' section, you will be able to update the microcode on
-@@ -434,6 +447,10 @@ config X86_CPUID
+@@ -434,6 +448,10 @@ config X86_CPUID
with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
/dev/cpu/31/cpuid.
@@ -86,7 +122,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
source "drivers/firmware/Kconfig"
choice
-@@ -616,6 +633,7 @@ config HIGHPTE
+@@ -616,6 +634,7 @@ config HIGHPTE
config MATH_EMULATION
bool "Math emulation"
@@ -94,12 +130,11 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
---help---
Linux can emulate a math coprocessor (used for floating point
operations) if you don't have one. 486DX and Pentium processors have
-@@ -641,6 +659,8 @@ config MATH_EMULATION
+@@ -641,6 +660,7 @@ config MATH_EMULATION
config MTRR
bool "MTRR (Memory Type Range Register) support"
+ depends on !XEN_UNPRIVILEGED_GUEST
-+ default y if X86_XEN
---help---
On Intel P6 family processors (Pentium Pro, Pentium II and later)
the Memory Type Range Registers (MTRRs) may be used to control
@@ -130,7 +165,15 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
-@@ -793,6 +813,7 @@ config HOTPLUG_CPU
+@@ -760,6 +780,7 @@ config CRASH_DUMP
+ bool "kernel crash dumps (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ depends on HIGHMEM
++ depends on !XEN
+ help
+ Generate crash dump after being started by kexec.
+
+@@ -793,6 +814,7 @@ config HOTPLUG_CPU
config COMPAT_VDSO
bool "Compat VDSO support"
@@ -138,7 +181,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
default y
help
Map the VDSO to the predictable old-style address too.
-@@ -810,18 +831,18 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
+@@ -810,18 +832,18 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
depends on HIGHMEM
menu "Power management options (ACPI, APM)"
@@ -161,7 +204,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
---help---
APM is a BIOS specification for saving power using several different
techniques. This is mostly useful for battery powered laptops with
-@@ -1006,6 +1027,7 @@ choice
+@@ -1006,6 +1028,7 @@ choice
config PCI_GOBIOS
bool "BIOS"
@@ -169,7 +212,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
config PCI_GOMMCONFIG
bool "MMConfig"
-@@ -1013,6 +1035,13 @@ config PCI_GOMMCONFIG
+@@ -1013,6 +1036,13 @@ config PCI_GOMMCONFIG
config PCI_GODIRECT
bool "Direct"
@@ -183,7 +226,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
config PCI_GOANY
bool "Any"
-@@ -1020,7 +1049,7 @@ endchoice
+@@ -1020,7 +1050,7 @@ endchoice
config PCI_BIOS
bool
@@ -192,13 +235,14 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
default y
config PCI_DIRECT
-@@ -1033,6 +1062,18 @@ config PCI_MMCONFIG
+@@ -1033,6 +1063,19 @@ config PCI_MMCONFIG
depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
default y
+config XEN_PCIDEV_FRONTEND
+ bool
+ depends on PCI && X86_XEN && (PCI_GOXEN_FE || PCI_GOANY)
++ select HOTPLUG
+ default y
+
+config XEN_PCIDEV_FE_DEBUG
@@ -211,7 +255,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
source "drivers/pci/pcie/Kconfig"
source "drivers/pci/Kconfig"
-@@ -1043,7 +1084,7 @@ config ISA_DMA_API
+@@ -1043,7 +1086,7 @@ config ISA_DMA_API
config ISA
bool "ISA support"
@@ -220,7 +264,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
help
Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff
-@@ -1070,7 +1111,7 @@ config EISA
+@@ -1070,7 +1113,7 @@ config EISA
source "drivers/eisa/Kconfig"
config MCA
@@ -229,7 +273,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
default y if X86_VOYAGER
help
MicroChannel Architecture is found in some IBM PS/2 machines and
-@@ -1146,6 +1187,8 @@ source "security/Kconfig"
+@@ -1146,6 +1189,8 @@ source "security/Kconfig"
source "crypto/Kconfig"
@@ -238,7 +282,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
source "lib/Kconfig"
#
-@@ -1171,7 +1214,7 @@ config X86_SMP
+@@ -1171,7 +1216,7 @@ config X86_SMP
config X86_HT
bool
@@ -247,10 +291,13 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
default y
config X86_BIOS_REBOOT
-@@ -1184,6 +1227,16 @@ config X86_TRAMPOLINE
+@@ -1182,6 +1227,17 @@ config X86_BIOS_REBOOT
+ config X86_TRAMPOLINE
+ bool
depends on X86_SMP || (X86_VOYAGER && SMP)
- default y
-
++ depends on !XEN
++ default y
++
+config X86_NO_TSS
+ bool
+ depends on X86_XEN
@@ -259,14 +306,12 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig linux-2.6.18-xen-3.2.0/arch/i386/Kco
+config X86_NO_IDT
+ bool
+ depends on X86_XEN
-+ default y
-+
- config KTIME_SCALAR
- bool
default y
-diff -rpuN linux-2.6.18.8/arch/i386/Kconfig.cpu linux-2.6.18-xen-3.2.0/arch/i386/Kconfig.cpu
---- linux-2.6.18.8/arch/i386/Kconfig.cpu 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/Kconfig.cpu 2008-02-15 16:21:49.000000000 -0800
+
+ config KTIME_SCALAR
+diff -rpuN linux-2.6.18.8/arch/i386/Kconfig.cpu linux-2.6.18-xen-3.3.0/arch/i386/Kconfig.cpu
+--- linux-2.6.18.8/arch/i386/Kconfig.cpu 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/Kconfig.cpu 2008-08-21 11:36:07.000000000 +0200
@@ -252,7 +252,7 @@ config X86_PPRO_FENCE
config X86_F00F_BUG
@@ -283,9 +328,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig.cpu linux-2.6.18-xen-3.2.0/arch/i386
- depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ
+ depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ && !X86_XEN
default y
-diff -rpuN linux-2.6.18.8/arch/i386/Kconfig.debug linux-2.6.18-xen-3.2.0/arch/i386/Kconfig.debug
---- linux-2.6.18.8/arch/i386/Kconfig.debug 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/Kconfig.debug 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/Kconfig.debug linux-2.6.18-xen-3.3.0/arch/i386/Kconfig.debug
+--- linux-2.6.18.8/arch/i386/Kconfig.debug 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/Kconfig.debug 2008-08-21 11:36:07.000000000 +0200
@@ -79,6 +79,7 @@ config X86_MPPARSE
config DOUBLEFAULT
default y
@@ -294,107 +339,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/Kconfig.debug linux-2.6.18-xen-3.2.0/arch/i3
help
This option allows trapping of rare doublefault exceptions that
would otherwise cause a system to silently reboot. Disabling this
-diff -rpuN linux-2.6.18.8/arch/i386/Makefile linux-2.6.18-xen-3.2.0/arch/i386/Makefile
---- linux-2.6.18.8/arch/i386/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -71,6 +71,10 @@ mcore-$(CONFIG_X86_BIGSMP) := mach-defau
- mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit
- mcore-$(CONFIG_X86_SUMMIT) := mach-default
-
-+# Xen subarch support
-+mflags-$(CONFIG_X86_XEN) := -Iinclude/asm-i386/mach-xen
-+mcore-$(CONFIG_X86_XEN) := mach-xen
-+
- # generic subarchitecture
- mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic
- mcore-$(CONFIG_X86_GENERICARCH) := mach-default
-@@ -102,9 +106,20 @@ AFLAGS += $(mflags-y)
-
- boot := arch/i386/boot
-
--PHONY += zImage bzImage compressed zlilo bzlilo \
-+PHONY += zImage bzImage vmlinuz compressed zlilo bzlilo \
- zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install
-
-+ifdef CONFIG_XEN
-+CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
-+ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS)
-+all: vmlinuz
-+
-+# KBUILD_IMAGE specifies the target image being built
-+KBUILD_IMAGE := $(boot)/vmlinuz
-+
-+vmlinuz: vmlinux
-+ $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
-+else
- all: bzImage
-
- # KBUILD_IMAGE specify target image being built
-@@ -124,6 +139,7 @@ zdisk bzdisk: vmlinux
-
- fdimage fdimage144 fdimage288 isoimage: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
-+endif
-
- install:
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
-diff -rpuN linux-2.6.18.8/arch/i386/boot/Makefile linux-2.6.18-xen-3.2.0/arch/i386/boot/Makefile
---- linux-2.6.18.8/arch/i386/boot/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/boot/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -26,7 +26,7 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
- #RAMDISK := -DRAMDISK=512
-
- targets := vmlinux.bin bootsect bootsect.o \
-- setup setup.o zImage bzImage
-+ setup setup.o zImage bzImage vmlinuz vmlinux-stripped
- subdir- := compressed
-
- hostprogs-y := tools/build
-@@ -133,5 +133,13 @@ zlilo: $(BOOTIMAGE)
- cp System.map $(INSTALL_PATH)/
- if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-
-+$(obj)/vmlinuz: $(obj)/vmlinux-stripped FORCE
-+ $(call if_changed,gzip)
-+ @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
-+
-+$(obj)/vmlinux-stripped: OBJCOPYFLAGS := -g --strip-unneeded
-+$(obj)/vmlinux-stripped: vmlinux FORCE
-+ $(call if_changed,objcopy)
-+
- install:
- sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/Makefile linux-2.6.18-xen-3.2.0/arch/i386/kernel/Makefile
---- linux-2.6.18.8/arch/i386/kernel/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -43,6 +43,7 @@ obj-$(CONFIG_K8_NB) += k8.o
- EXTRA_AFLAGS := -traditional
-
- obj-$(CONFIG_SCx200) += scx200.o
-+obj-$(CONFIG_XEN) += fixup.o
-
- # vsyscall.o contains the vsyscall DSO images as __initdata.
- # We must build both images before we can assemble it.
-@@ -80,5 +81,8 @@ $(obj)/vsyscall-syms.o: $(src)/vsyscall.
- $(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
- $(call if_changed,syscall)
-
-+early_printk-y += ../../x86_64/kernel/early_printk.o
- k8-y += ../../x86_64/kernel/k8.o
-
-+disabled-obj-$(CONFIG_XEN) := i8259.o reboot.o smpboot.o trampoline.o
-+%/head.o %/head.s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/Makefile linux-2.6.18-xen-3.2.0/arch/i386/kernel/acpi/Makefile
---- linux-2.6.18.8/arch/i386/kernel/acpi/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/acpi/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -6,3 +6,4 @@ ifneq ($(CONFIG_ACPI_PROCESSOR),)
- obj-y += cstate.o processor.o
- endif
-
-+disabled-obj-$(CONFIG_XEN) := cstate.o wakeup.o
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/boot-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/acpi/boot-xen.c
---- linux-2.6.18.8/arch/i386/kernel/acpi/boot-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/acpi/boot-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/boot-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/boot-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/acpi/boot-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/boot-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1168 @@
+/*
+ * boot.c - Architecture-Specific Low-Level ACPI Boot Support
@@ -1564,10 +1511,278 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/boot-xen.c linux-2.6.18-xen-3.2.
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/sleep-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/acpi/sleep-xen.c
---- linux-2.6.18.8/arch/i386/kernel/acpi/sleep-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/acpi/sleep-xen.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,134 @@
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/Makefile linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/Makefile
+--- linux-2.6.18.8/arch/i386/kernel/acpi/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -4,5 +4,9 @@ obj-$(CONFIG_ACPI_SLEEP) += sleep.o wake
+
+ ifneq ($(CONFIG_ACPI_PROCESSOR),)
+ obj-y += cstate.o processor.o
++ifneq ($(CONFIG_PROCESSOR_EXTERNAL_CONTROL),)
++obj-$(CONFIG_XEN) += processor_extcntl_xen.o
++endif
+ endif
+
++disabled-obj-$(CONFIG_XEN) := cstate.o wakeup.o
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/processor.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/processor.c
+--- linux-2.6.18.8/arch/i386/kernel/acpi/processor.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/processor.c 2008-08-21 11:36:07.000000000 +0200
+@@ -62,7 +62,18 @@ static void init_intel_pdc(struct acpi_p
+ /* Initialize _PDC data based on the CPU vendor */
+ void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
+ {
++#ifdef CONFIG_XEN
++ /*
++ * As a work-around, just use cpu0's cpuinfo for all processors.
++ * Further work is required to expose xen hypervisor interface of
++ * getting physical cpuinfo to dom0 kernel and then
++ * arch_acpi_processor_init_pdc can set _PDC parameters according
++ * to Xen's phys information.
++ */
++ unsigned int cpu = 0;
++#else
+ unsigned int cpu = pr->id;
++#endif /* CONFIG_XEN */
+ struct cpuinfo_x86 *c = cpu_data + cpu;
+
+ pr->pdc = NULL;
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/processor_extcntl_xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/processor_extcntl_xen.c
+--- linux-2.6.18.8/arch/i386/kernel/acpi/processor_extcntl_xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/processor_extcntl_xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,229 @@
++/*
++ * processor_extcntl_xen.c - interface to notify Xen
++ *
++ * Copyright (C) 2008, Intel corporation
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * 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; either version 2 of the License, or (at
++ * your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/acpi.h>
++#include <linux/pm.h>
++#include <linux/cpu.h>
++
++#include <linux/cpufreq.h>
++#include <acpi/processor.h>
++#include <asm/hypercall.h>
++
++static int xen_processor_pmbits;
++
++static int xen_cx_notifier(struct acpi_processor *pr, int action)
++{
++ int ret, count = 0, i;
++ xen_platform_op_t op = {
++ .cmd = XENPF_set_processor_pminfo,
++ .interface_version = XENPF_INTERFACE_VERSION,
++ .u.set_pminfo.id = pr->acpi_id,
++ .u.set_pminfo.type = XEN_PM_CX,
++ };
++ struct xen_processor_cx *data, *buf;
++ struct acpi_processor_cx *cx;
++
++ if (action == PROCESSOR_PM_CHANGE)
++ return -EINVAL;
++
++ /* Convert to Xen defined structure and hypercall */
++ buf = kzalloc(pr->power.count * sizeof(struct xen_processor_cx),
++ GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ data = buf;
++ for (i = 1; i <= pr->power.count; i++) {
++ cx = &pr->power.states[i];
++ /* Skip invalid cstate entry */
++ if (!cx->valid)
++ continue;
++
++ data->type = cx->type;
++ data->latency = cx->latency;
++ data->power = cx->power;
++ data->reg.space_id = cx->reg.space_id;
++ data->reg.bit_width = cx->reg.bit_width;
++ data->reg.bit_offset = cx->reg.bit_offset;
++ data->reg.access_size = cx->reg.reserved;
++ data->reg.address = cx->reg.address;
++
++ /* Get dependency relationships */
++ if (cx->csd_count) {
++ printk("Wow! _CSD is found. Not support for now!\n");
++ kfree(buf);
++ return -EINVAL;
++ } else {
++ data->dpcnt = 0;
++ set_xen_guest_handle(data->dp, NULL);
++ }
++
++ data++;
++ count++;
++ }
++
++ if (!count) {
++ printk("No available Cx info for cpu %d\n", pr->acpi_id);
++ kfree(buf);
++ return -EINVAL;
++ }
++
++ op.u.set_pminfo.power.count = count;
++ op.u.set_pminfo.power.flags.bm_control = pr->flags.bm_control;
++ op.u.set_pminfo.power.flags.bm_check = pr->flags.bm_check;
++ op.u.set_pminfo.power.flags.has_cst = pr->flags.has_cst;
++ op.u.set_pminfo.power.flags.power_setup_done = pr->flags.power_setup_done;
++
++ set_xen_guest_handle(op.u.set_pminfo.power.states, buf);
++ ret = HYPERVISOR_platform_op(&op);
++ kfree(buf);
++ return ret;
++}
++
++static void convert_pct_reg(struct xen_pct_register *xpct,
++ struct acpi_pct_register *apct)
++{
++ xpct->descriptor = apct->descriptor;
++ xpct->length = apct->length;
++ xpct->space_id = apct->space_id;
++ xpct->bit_width = apct->bit_width;
++ xpct->bit_offset = apct->bit_offset;
++ xpct->reserved = apct->reserved;
++ xpct->address = apct->address;
++}
++
++static void convert_pss_states(struct xen_processor_px *xpss,
++ struct acpi_processor_px *apss, int state_count)
++{
++ int i;
++ for(i=0; i<state_count; i++) {
++ xpss->core_frequency = apss->core_frequency;
++ xpss->power = apss->power;
++ xpss->transition_latency = apss->transition_latency;
++ xpss->bus_master_latency = apss->bus_master_latency;
++ xpss->control = apss->control;
++ xpss->status = apss->status;
++ xpss++;
++ apss++;
++ }
++}
++
++static void convert_psd_pack(struct xen_psd_package *xpsd,
++ struct acpi_psd_package *apsd)
++{
++ xpsd->num_entries = apsd->num_entries;
++ xpsd->revision = apsd->revision;
++ xpsd->domain = apsd->domain;
++ xpsd->coord_type = apsd->coord_type;
++ xpsd->num_processors = apsd->num_processors;
++}
++
++static int xen_px_notifier(struct acpi_processor *pr, int action)
++{
++ int ret;
++ xen_platform_op_t op = {
++ .cmd = XENPF_set_processor_pminfo,
++ .interface_version = XENPF_INTERFACE_VERSION,
++ .u.set_pminfo.id = pr->acpi_id,
++ .u.set_pminfo.type = XEN_PM_PX,
++ };
++ struct xen_processor_performance *perf;
++ struct xen_processor_px *states = NULL;
++ struct acpi_processor_performance *px;
++ struct acpi_psd_package *pdomain;
++
++ /* leave dynamic ppc handle in the future */
++ if (action == PROCESSOR_PM_CHANGE)
++ return 0;
++
++ perf = &op.u.set_pminfo.perf;
++ px = pr->performance;
++
++ perf->flags = XEN_PX_PPC |
++ XEN_PX_PCT |
++ XEN_PX_PSS |
++ XEN_PX_PSD;
++
++ /* ppc */
++ perf->ppc = pr->performance_platform_limit;
++
++ /* pct */
++ convert_pct_reg(&perf->control_register, &px->control_register);
++ convert_pct_reg(&perf->status_register, &px->status_register);
++
++ /* pss */
++ perf->state_count = px->state_count;
++ states = kzalloc(px->state_count*sizeof(xen_processor_px_t),GFP_KERNEL);
++ if (!states)
++ return -ENOMEM;
++ convert_pss_states(states, px->states, px->state_count);
++ set_xen_guest_handle(perf->states, states);
++
++ /* psd */
++ pdomain = &px->domain_info;
++ convert_psd_pack(&perf->domain_info, pdomain);
++ if (perf->domain_info.num_processors) {
++ if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
++ perf->shared_type = CPUFREQ_SHARED_TYPE_ALL;
++ else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
++ perf->shared_type = CPUFREQ_SHARED_TYPE_ANY;
++ else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
++ perf->shared_type = CPUFREQ_SHARED_TYPE_HW;
++ } else
++ perf->shared_type = CPUFREQ_SHARED_TYPE_NONE;
++
++ ret = HYPERVISOR_platform_op(&op);
++ kfree(states);
++ return ret;
++}
++
++static int xen_tx_notifier(struct acpi_processor *pr, int action)
++{
++ return -EINVAL;
++}
++static int xen_hotplug_notifier(struct acpi_processor *pr, int event)
++{
++ return -EINVAL;
++}
++
++static struct processor_extcntl_ops xen_extcntl_ops = {
++ .hotplug = xen_hotplug_notifier,
++};
++
++void arch_acpi_processor_init_extcntl(const struct processor_extcntl_ops **ops)
++{
++ xen_processor_pmbits = (xen_start_info->flags & SIF_PM_MASK) >> 8;
++
++ if (xen_processor_pmbits & XEN_PROCESSOR_PM_CX)
++ xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier;
++ if (xen_processor_pmbits & XEN_PROCESSOR_PM_PX)
++ xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier;
++ if (xen_processor_pmbits & XEN_PROCESSOR_PM_TX)
++ xen_extcntl_ops.pm_ops[PM_TYPE_THR] = xen_tx_notifier;
++
++ *ops = &xen_extcntl_ops;
++}
++EXPORT_SYMBOL(arch_acpi_processor_init_extcntl);
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/sleep-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/sleep-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/acpi/sleep-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/acpi/sleep-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,113 @@
+/*
+ * sleep.c - x86-specific ACPI sleep support.
+ *
@@ -1680,31 +1895,10 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/acpi/sleep-xen.c linux-2.6.18-xen-3.2
+}
+
+core_initcall(acpisleep_dmi_init);
-+
-+#else /* CONFIG_ACPI_PV_SLEEP */
-+#include <asm/hypervisor.h>
-+#include <xen/interface/platform.h>
-+int acpi_notify_hypervisor_state(u8 sleep_state,
-+ u32 pm1a_cnt, u32 pm1b_cnt)
-+{
-+ struct xen_platform_op op = {
-+ .cmd = XENPF_enter_acpi_sleep,
-+ .interface_version = XENPF_INTERFACE_VERSION,
-+ .u = {
-+ .enter_acpi_sleep = {
-+ .pm1a_cnt_val = (u16)pm1a_cnt,
-+ .pm1b_cnt_val = (u16)pm1b_cnt,
-+ .sleep_state = sleep_state,
-+ },
-+ },
-+ };
-+
-+ return HYPERVISOR_platform_op(&op);
-+}
+#endif /* CONFIG_ACPI_PV_SLEEP */
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/apic-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/apic-xen.c
---- linux-2.6.18.8/arch/i386/kernel/apic-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/apic-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/apic-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/apic-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/apic-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/apic-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,155 @@
+/*
+ * Local APIC handling, local APIC timers
@@ -1861,9 +2055,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/apic-xen.c linux-2.6.18-xen-3.2.0/arc
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/asm-offsets.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/asm-offsets.c
---- linux-2.6.18.8/arch/i386/kernel/asm-offsets.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/asm-offsets.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/asm-offsets.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/asm-offsets.c
+--- linux-2.6.18.8/arch/i386/kernel/asm-offsets.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/asm-offsets.c 2008-08-21 11:36:07.000000000 +0200
@@ -66,9 +66,14 @@ void foo(void)
OFFSET(pbe_orig_address, pbe, orig_address);
OFFSET(pbe_next, pbe, next);
@@ -1880,17 +2074,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/asm-offsets.c linux-2.6.18-xen-3.2.0/
DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
DEFINE(VDSO_PRELINK, VDSO_PRELINK);
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/Makefile linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/Makefile
---- linux-2.6.18.8/arch/i386/kernel/cpu/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -17,3 +17,4 @@ obj-$(CONFIG_X86_MCE) += mcheck/
-
- obj-$(CONFIG_MTRR) += mtrr/
- obj-$(CONFIG_CPU_FREQ) += cpufreq/
-+
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/common-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/common-xen.c
---- linux-2.6.18.8/arch/i386/kernel/cpu/common-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/common-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/common-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/common-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/cpu/common-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/common-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,743 @@
+#include <linux/init.h>
+#include <linux/string.h>
@@ -2635,9 +2821,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/common-xen.c linux-2.6.18-xen-3.2
+ per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm;
+}
+#endif
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
---- linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+--- linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2008-08-21 11:36:07.000000000 +0200
@@ -46,7 +46,7 @@
#define PFX "powernow-k8: "
@@ -3074,9 +3260,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.c linux-2.6.1
printk(KERN_INFO PFX "Found %d %s "
"processors (" VERSION ")\n", supported_cpus,
boot_cpu_data.x86_model_id);
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.h linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
---- linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.h linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+--- linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2008-08-21 11:36:07.000000000 +0200
@@ -1,5 +1,5 @@
/*
- * (c) 2003-2006 Advanced Micro Devices, Inc.
@@ -3147,17 +3333,17 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/cpufreq/powernow-k8.h linux-2.6.1
/* define the two driver architectures */
#define CPU_OPTERON 0
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/Makefile linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/mtrr/Makefile
---- linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/mtrr/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -3,3 +3,4 @@ obj-y += amd.o
- obj-y += cyrix.o
- obj-y += centaur.o
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/Makefile linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/Makefile
+--- linux-2.6.18.8/arch/i386/kernel/cpu/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -17,3 +17,4 @@ obj-$(CONFIG_X86_MCE) += mcheck/
-+obj-$(CONFIG_XEN) := main.o if.o
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/main-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/mtrr/main-xen.c
---- linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/main-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/cpu/mtrr/main-xen.c 2008-02-15 16:21:49.000000000 -0800
+ obj-$(CONFIG_MTRR) += mtrr/
+ obj-$(CONFIG_CPU_FREQ) += cpufreq/
++
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/main-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/mtrr/main-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/main-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/mtrr/main-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,198 @@
+#include <linux/init.h>
+#include <linux/proc_fs.h>
@@ -3357,9 +3543,17 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/main-xen.c linux-2.6.18-xen-
+}
+
+subsys_initcall(mtrr_init);
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/crash.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/crash.c
---- linux-2.6.18.8/arch/i386/kernel/crash.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/crash.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/Makefile linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/mtrr/Makefile
+--- linux-2.6.18.8/arch/i386/kernel/cpu/mtrr/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/cpu/mtrr/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -3,3 +3,4 @@ obj-y += amd.o
+ obj-y += cyrix.o
+ obj-y += centaur.o
+
++obj-$(CONFIG_XEN) := main.o if.o
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/crash.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/crash.c
+--- linux-2.6.18.8/arch/i386/kernel/crash.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/crash.c 2008-08-21 11:36:07.000000000 +0200
@@ -90,6 +90,7 @@ static void crash_save_self(struct pt_re
crash_save_this_cpu(regs, cpu);
}
@@ -3389,15 +3583,45 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/crash.c linux-2.6.18-xen-3.2.0/arch/i
+#endif /* CONFIG_XEN */
crash_save_self(regs);
}
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/early_printk-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/early_printk-xen.c
---- linux-2.6.18.8/arch/i386/kernel/early_printk-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/early_printk-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/early_printk-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/early_printk-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/early_printk-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/early_printk-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,2 @@
+
+#include "../../x86_64/kernel/early_printk-xen.c"
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/entry-xen.S linux-2.6.18-xen-3.2.0/arch/i386/kernel/entry-xen.S
---- linux-2.6.18.8/arch/i386/kernel/entry-xen.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/entry-xen.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/entry.S linux-2.6.18-xen-3.3.0/arch/i386/kernel/entry.S
+--- linux-2.6.18.8/arch/i386/kernel/entry.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/entry.S 2008-08-21 11:36:07.000000000 +0200
+@@ -269,7 +269,7 @@ ENTRY(sysenter_entry)
+ CFI_STARTPROC simple
+ CFI_DEF_CFA esp, 0
+ CFI_REGISTER esp, ebp
+- movl TSS_sysenter_esp0(%esp),%esp
++ movl SYSENTER_stack_esp0(%esp),%esp
+ sysenter_past_esp:
+ /*
+ * No need to follow this irqs on/off section: the syscall
+@@ -689,7 +689,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.
+ *
+@@ -701,7 +701,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 -rpuN linux-2.6.18.8/arch/i386/kernel/entry-xen.S linux-2.6.18-xen-3.3.0/arch/i386/kernel/entry-xen.S
+--- linux-2.6.18.8/arch/i386/kernel/entry-xen.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/entry-xen.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1238 @@
+/*
+ * linux/arch/i386/entry.S
@@ -4637,39 +4861,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/entry-xen.S linux-2.6.18-xen-3.2.0/ar
+#include "syscall_table.S"
+
+syscall_table_size=(.-sys_call_table)
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/entry.S linux-2.6.18-xen-3.2.0/arch/i386/kernel/entry.S
---- linux-2.6.18.8/arch/i386/kernel/entry.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/entry.S 2008-02-15 16:21:49.000000000 -0800
-@@ -269,7 +269,7 @@ ENTRY(sysenter_entry)
- CFI_STARTPROC simple
- CFI_DEF_CFA esp, 0
- CFI_REGISTER esp, ebp
-- movl TSS_sysenter_esp0(%esp),%esp
-+ movl SYSENTER_stack_esp0(%esp),%esp
- sysenter_past_esp:
- /*
- * No need to follow this irqs on/off section: the syscall
-@@ -689,7 +689,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.
- *
-@@ -701,7 +701,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 -rpuN linux-2.6.18.8/arch/i386/kernel/fixup.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/fixup.c
---- linux-2.6.18.8/arch/i386/kernel/fixup.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/fixup.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/fixup.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/fixup.c
+--- linux-2.6.18.8/arch/i386/kernel/fixup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/fixup.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * fixup.c
@@ -4759,9 +4953,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/fixup.c linux-2.6.18-xen-3.2.0/arch/i
+ return 0;
+}
+__initcall(fixup_init);
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/head-xen.S linux-2.6.18-xen-3.2.0/arch/i386/kernel/head-xen.S
---- linux-2.6.18.8/arch/i386/kernel/head-xen.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/head-xen.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/head-xen.S linux-2.6.18-xen-3.3.0/arch/i386/kernel/head-xen.S
+--- linux-2.6.18.8/arch/i386/kernel/head-xen.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/head-xen.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,207 @@
+
+
@@ -4970,9 +5164,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/head-xen.S linux-2.6.18-xen-3.2.0/arc
+#endif
+ ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic")
+ ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long, 1)
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/init_task-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/init_task-xen.c
---- linux-2.6.18.8/arch/i386/kernel/init_task-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/init_task-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/init_task-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/init_task-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/init_task-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/init_task-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,51 @@
+#include <linux/mm.h>
+#include <linux/module.h>
@@ -5025,9 +5219,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/init_task-xen.c linux-2.6.18-xen-3.2.
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
+#endif
+
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/io_apic-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/io_apic-xen.c
---- linux-2.6.18.8/arch/i386/kernel/io_apic-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/io_apic-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/io_apic-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/io_apic-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/io_apic-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/io_apic-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,2770 @@
+/*
+ * Intel IO-APIC support for multi-Pentium hosts.
@@ -7799,9 +7993,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/io_apic-xen.c linux-2.6.18-xen-3.2.0/
+}
+
+#endif /* CONFIG_ACPI */
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/ioport-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/ioport-xen.c
---- linux-2.6.18.8/arch/i386/kernel/ioport-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/ioport-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/ioport-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/ioport-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/ioport-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/ioport-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/i386/kernel/ioport.c
@@ -7926,9 +8120,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/ioport-xen.c linux-2.6.18-xen-3.2.0/a
+ set_iopl_mask(t->iopl);
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/irq-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/irq-xen.c
---- linux-2.6.18.8/arch/i386/kernel/irq-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/irq-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/irq-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/irq-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/irq-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/irq-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,324 @@
+/*
+ * linux/arch/i386/kernel/irq.c
@@ -8254,9 +8448,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/irq-xen.c linux-2.6.18-xen-3.2.0/arch
+}
+#endif
+
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/ldt-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/ldt-xen.c
---- linux-2.6.18.8/arch/i386/kernel/ldt-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/ldt-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/ldt-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/ldt-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/ldt-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/ldt-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,270 @@
+/*
+ * linux/kernel/ldt.c
@@ -8528,10 +8722,10 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/ldt-xen.c linux-2.6.18-xen-3.2.0/arch
+ }
+ return ret;
+}
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/machine_kexec.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/machine_kexec.c
---- linux-2.6.18.8/arch/i386/kernel/machine_kexec.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/machine_kexec.c 2008-02-15 16:21:49.000000000 -0800
-@@ -19,123 +19,52 @@
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/machine_kexec.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/machine_kexec.c
+--- linux-2.6.18.8/arch/i386/kernel/machine_kexec.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/machine_kexec.c 2008-08-21 11:36:07.000000000 +0200
+@@ -19,123 +19,67 @@
#include <asm/desc.h>
#include <asm/system.h>
@@ -8554,7 +8748,10 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/machine_kexec.c linux-2.6.18-xen-3.2.
-
- /* Find the current page table */
- pgtable_level2 = __va(read_cr3());
--
++#ifdef CONFIG_XEN
++#include <xen/interface/kexec.h>
++#endif
+
- /* Find the indexes of the physical address to identity map */
- level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
- level2_index = address / LEVEL1_SIZE;
@@ -8568,22 +8765,32 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/machine_kexec.c linux-2.6.18-xen-3.2.
- */
- load_cr3(pgtable_level2);
-}
--
++#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
++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;
+
-#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;
--
++#ifdef CONFIG_XEN
+
-static void identity_map_page(unsigned long address)
-{
- unsigned long level1_index, level2_index, level3_index;
- u64 *pgtable_level3;
--
++#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
+
- /* Find the current page table */
- pgtable_level3 = __va(read_cr3());
-+#ifdef CONFIG_XEN
-+#include <xen/interface/kexec.h>
++#if PAGES_NR > KEXEC_XEN_NO_PAGES
++#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
+#endif
- /* Find the indexes of the physical address to identity map */
@@ -8602,63 +8809,59 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/machine_kexec.c linux-2.6.18-xen-3.2.
- */
- load_cr3(pgtable_level3);
-}
-+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
-+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;
++#if PA_CONTROL_PAGE != 0
++#error PA_CONTROL_PAGE is non zero - Xen support will break
#endif
-+static u32 kexec_pte0[1024] PAGE_ALIGNED;
-+static u32 kexec_pte1[1024] PAGE_ALIGNED;
-static void set_idt(void *newidt, __u16 limit)
--{
++void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
+ {
- struct Xgt_desc_struct curidt;
-+#ifdef CONFIG_XEN
++ void *control_page;
- /* ia32 supports unaliged loads & stores */
- curidt.size = limit;
- curidt.address = (unsigned long)newidt;
-+#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
++ memset(xki->page_list, 0, sizeof(xki->page_list));
- load_idt(&curidt);
-};
-+#if PAGES_NR > KEXEC_XEN_NO_PAGES
-+#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
-+#endif
++ control_page = page_address(image->control_code_page);
++ memcpy(control_page, relocate_kernel, PAGE_SIZE);
-+#if PA_CONTROL_PAGE != 0
-+#error PA_CONTROL_PAGE is non zero - Xen support will break
++ xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
++ xki->page_list[PA_PGD] = __ma(kexec_pgd);
++#ifdef CONFIG_X86_PAE
++ xki->page_list[PA_PMD_0] = __ma(kexec_pmd0);
++ xki->page_list[PA_PMD_1] = __ma(kexec_pmd1);
+#endif
++ xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
++ xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
-static void set_gdt(void *newgdt, __u16 limit)
-+void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
- {
+-{
- struct Xgt_desc_struct curgdt;
-+ void *control_page;
-
+-
- /* ia32 supports unaligned loads & stores */
- curgdt.size = limit;
- curgdt.address = (unsigned long)newgdt;
-+ memset(xki->page_list, 0, sizeof(xki->page_list));
-
+-
- load_gdt(&curgdt);
-};
-+ control_page = page_address(image->control_code_page);
-+ memcpy(control_page, relocate_kernel, PAGE_SIZE);
++}
-static void load_segments(void)
--{
++int __init machine_kexec_setup_resources(struct resource *hypervisor,
++ struct resource *phys_cpus,
++ int nr_phys_cpus)
+ {
-#define __STR(X) #X
-#define STR(X) __STR(X)
-+ xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
-+ xki->page_list[PA_PGD] = __ma(kexec_pgd);
-+#ifdef CONFIG_X86_PAE
-+ xki->page_list[PA_PMD_0] = __ma(kexec_pmd0);
-+ xki->page_list[PA_PMD_1] = __ma(kexec_pmd1);
-+#endif
-+ xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
-+ xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
++ int k;
++
++ /* The per-cpu crash note resources belong to the hypervisor resource */
++ for (k = 0; k < nr_phys_cpus; k++)
++ request_resource(hypervisor, phys_cpus + k);
- __asm__ __volatile__ (
- "\tljmp $"STR(__KERNEL_CS)",$1f\n"
@@ -8672,6 +8875,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/machine_kexec.c linux-2.6.18-xen-3.2.
- ::: "eax", "memory");
-#undef STR
-#undef __STR
++ return 0;
}
-typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
@@ -8683,11 +8887,13 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/machine_kexec.c linux-2.6.18-xen-3.2.
-extern const unsigned char relocate_new_kernel[];
-extern void relocate_new_kernel_end(void);
-extern const unsigned int relocate_new_kernel_size;
++void machine_kexec_register_resources(struct resource *res) { ; }
++
+#endif /* CONFIG_XEN */
/*
* A architecture hook called to validate the
-@@ -163,49 +92,38 @@ void machine_kexec_cleanup(struct kimage
+@@ -163,49 +107,38 @@ void machine_kexec_cleanup(struct kimage
{
}
@@ -8761,9 +8967,29 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/machine_kexec.c linux-2.6.18-xen-3.2.
+ image->start, cpu_has_pae);
}
+#endif
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/microcode-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/microcode-xen.c
---- linux-2.6.18.8/arch/i386/kernel/microcode-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/microcode-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/Makefile linux-2.6.18-xen-3.3.0/arch/i386/kernel/Makefile
+--- linux-2.6.18.8/arch/i386/kernel/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -43,6 +43,7 @@ obj-$(CONFIG_K8_NB) += k8.o
+ EXTRA_AFLAGS := -traditional
+
+ obj-$(CONFIG_SCx200) += scx200.o
++obj-$(CONFIG_XEN) += fixup.o
+
+ # vsyscall.o contains the vsyscall DSO images as __initdata.
+ # We must build both images before we can assemble it.
+@@ -80,5 +81,8 @@ $(obj)/vsyscall-syms.o: $(src)/vsyscall.
+ $(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
+ $(call if_changed,syscall)
+
++early_printk-y += ../../x86_64/kernel/early_printk.o
+ k8-y += ../../x86_64/kernel/k8.o
+
++disabled-obj-$(CONFIG_XEN) := i8259.o reboot.o smpboot.o
++%/head.o %/head.s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/microcode-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/microcode-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/microcode-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/microcode-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,144 @@
+/*
+ * Intel CPU Microcode Update Driver for Linux
@@ -8909,9 +9135,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/microcode-xen.c linux-2.6.18-xen-3.2.
+module_init(microcode_init)
+module_exit(microcode_exit)
+MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/mpparse-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/mpparse-xen.c
---- linux-2.6.18.8/arch/i386/kernel/mpparse-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/mpparse-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/mpparse-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/mpparse-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/mpparse-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/mpparse-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1185 @@
+/*
+ * Intel Multiprocessor Specification 1.1 and 1.4
@@ -10098,10 +10324,10 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/mpparse-xen.c linux-2.6.18-xen-3.2.0/
+
+#endif /* CONFIG_X86_IO_APIC */
+#endif /* CONFIG_ACPI */
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/pci-dma-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/pci-dma-xen.c
---- linux-2.6.18.8/arch/i386/kernel/pci-dma-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/pci-dma-xen.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,382 @@
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/pci-dma-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/pci-dma-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/pci-dma-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/pci-dma-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,415 @@
+/*
+ * Dynamic DMA mapping support.
+ *
@@ -10181,6 +10407,39 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/pci-dma-xen.c linux-2.6.18-xen-3.2.0/
+ } \
+} while (0)
+
++static int check_pages_physically_contiguous(unsigned long pfn,
++ unsigned int offset,
++ size_t length)
++{
++ unsigned long next_mfn;
++ int i;
++ int nr_pages;
++
++ next_mfn = pfn_to_mfn(pfn);
++ nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT;
++
++ for (i = 1; i < nr_pages; i++) {
++ if (pfn_to_mfn(++pfn) != ++next_mfn)
++ return 0;
++ }
++ return 1;
++}
++
++int range_straddles_page_boundary(paddr_t p, size_t size)
++{
++ extern unsigned long *contiguous_bitmap;
++ unsigned long pfn = p >> PAGE_SHIFT;
++ unsigned int offset = p & ~PAGE_MASK;
++
++ if (offset + size <= PAGE_SIZE)
++ return 0;
++ if (test_bit(pfn, contiguous_bitmap))
++ return 0;
++ if (check_pages_physically_contiguous(pfn, offset, size))
++ return 0;
++ return 1;
++}
++
+int
+dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
@@ -10484,10 +10743,10 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/pci-dma-xen.c linux-2.6.18-xen-3.2.0/
+ swiotlb_sync_single_for_device(dev, dma_handle, size, direction);
+}
+EXPORT_SYMBOL(dma_sync_single_for_device);
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/process-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/process-xen.c
---- linux-2.6.18.8/arch/i386/kernel/process-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/process-xen.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,856 @@
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/process-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/process-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/process-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/process-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,877 @@
+/*
+ * linux/arch/i386/kernel/process.c
+ *
@@ -11042,8 +11301,14 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/process-xen.c linux-2.6.18-xen-3.2.0/
+#ifndef CONFIG_X86_NO_TSS
+ struct tss_struct *tss = &per_cpu(init_tss, cpu);
+#endif
++#if CONFIG_XEN_COMPAT > 0x030002
+ struct physdev_set_iopl iopl_op;
+ struct physdev_set_iobitmap iobmp_op;
++#else
++ struct physdev_op _pdo[2], *pdo = _pdo;
++#define iopl_op pdo->u.set_iopl
++#define iobmp_op pdo->u.set_iobitmap
++#endif
+ multicall_entry_t _mcl[8], *mcl = _mcl;
+
+ /* XEN NOTE: FS/GS saved in switch_mm(), not here. */
@@ -11091,9 +11356,15 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/process-xen.c linux-2.6.18-xen-3.2.0/
+
+ if (unlikely(prev->iopl != next->iopl)) {
+ iopl_op.iopl = (next->iopl == 0) ? 1 : (next->iopl >> 12) & 3;
++#if CONFIG_XEN_COMPAT > 0x030002
+ mcl->op = __HYPERVISOR_physdev_op;
+ mcl->args[0] = PHYSDEVOP_set_iopl;
+ mcl->args[1] = (unsigned long)&iopl_op;
++#else
++ mcl->op = __HYPERVISOR_physdev_op_compat;
++ pdo->cmd = PHYSDEVOP_set_iopl;
++ mcl->args[0] = (unsigned long)pdo++;
++#endif
+ mcl++;
+ }
+
@@ -11101,12 +11372,21 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/process-xen.c linux-2.6.18-xen-3.2.0/
+ set_xen_guest_handle(iobmp_op.bitmap,
+ (char *)next->io_bitmap_ptr);
+ iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0;
++#if CONFIG_XEN_COMPAT > 0x030002
+ mcl->op = __HYPERVISOR_physdev_op;
+ mcl->args[0] = PHYSDEVOP_set_iobitmap;
+ mcl->args[1] = (unsigned long)&iobmp_op;
++#else
++ mcl->op = __HYPERVISOR_physdev_op_compat;
++ pdo->cmd = PHYSDEVOP_set_iobitmap;
++ mcl->args[0] = (unsigned long)pdo++;
++#endif
+ mcl++;
+ }
+
++#if CONFIG_XEN_COMPAT <= 0x030002
++ BUG_ON(pdo > _pdo + ARRAY_SIZE(_pdo));
++#endif
+ BUG_ON(mcl > _mcl + ARRAY_SIZE(_mcl));
+ if (unlikely(HYPERVISOR_multicall_check(_mcl, mcl - _mcl, NULL)))
+ BUG();
@@ -11344,9 +11624,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/process-xen.c linux-2.6.18-xen-3.2.0/
+ sp -= get_random_int() % 8192;
+ return sp & ~0xf;
+}
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/quirks-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/quirks-xen.c
---- linux-2.6.18.8/arch/i386/kernel/quirks-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/quirks-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/quirks-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/quirks-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/quirks-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/quirks-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,47 @@
+/*
+ * This file contains work-arounds for x86 and x86_64 platform bugs.
@@ -11395,9 +11675,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/quirks-xen.c linux-2.6.18-xen-3.2.0/a
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance);
+#endif
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/relocate_kernel.S linux-2.6.18-xen-3.2.0/arch/i386/kernel/relocate_kernel.S
---- linux-2.6.18.8/arch/i386/kernel/relocate_kernel.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/relocate_kernel.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/relocate_kernel.S linux-2.6.18-xen-3.3.0/arch/i386/kernel/relocate_kernel.S
+--- linux-2.6.18.8/arch/i386/kernel/relocate_kernel.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/relocate_kernel.S 2008-08-21 11:36:07.000000000 +0200
@@ -7,16 +7,138 @@
*/
@@ -11630,10 +11910,56 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+idt_48:
+ .word 0 /* limit */
+ .long 0 /* base */
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/setup-xen.c
---- linux-2.6.18.8/arch/i386/kernel/setup-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/setup-xen.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,1919 @@
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/setup.c
+--- linux-2.6.18.8/arch/i386/kernel/setup.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/setup.c 2008-08-21 11:36:07.000000000 +0200
+@@ -261,7 +261,12 @@ static struct resource standard_io_resou
+ }, {
+ .name = "keyboard",
+ .start = 0x0060,
+- .end = 0x006f,
++ .end = 0x0060,
++ .flags = IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++ .name = "keyboard",
++ .start = 0x0064,
++ .end = 0x0064,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+ .name = "dma page reg",
+@@ -956,6 +961,28 @@ efi_memory_present_wrapper(unsigned long
+ return 0;
+ }
+
++/*
++ * This function checks if any part of the range <start,end> is mapped
++ * with type.
++ */
++int
++e820_any_mapped(u64 start, u64 end, unsigned type)
++{
++ int i;
++
++ for (i = 0; i < e820.nr_map; i++) {
++ const struct e820entry *ei = &e820.map[i];
++
++ if (type && ei->type != type)
++ continue;
++ if (ei->addr >= end || ei->addr + ei->size <= start)
++ continue;
++ return 1;
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(e820_any_mapped);
++
+ /*
+ * This function checks if the entire range <start,end> is mapped with type.
+ *
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/setup-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/setup-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/setup-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1924 @@
+/*
+ * linux/arch/i386/kernel/setup.c
+ *
@@ -11919,7 +12245,12 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/ar
+}, {
+ .name = "keyboard",
+ .start = 0x0060,
-+ .end = 0x006f,
++ .end = 0x0060,
++ .flags = IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++ .name = "keyboard",
++ .start = 0x0064,
++ .end = 0x0064,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+ .name = "dma page reg",
@@ -12372,6 +12703,21 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/ar
+#endif
+ add_memory_region(start, size, type);
+ } while (biosmap++,--nr_map);
++
++#ifdef CONFIG_XEN
++ if (is_initial_xendomain()) {
++ struct xen_memory_map memmap;
++
++ memmap.nr_entries = E820MAX;
++ set_xen_guest_handle(memmap.buffer, machine_e820.map);
++
++ if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap))
++ BUG();
++ machine_e820.nr_map = memmap.nr_entries;
++ } else
++ machine_e820 = e820;
++#endif
++
+ return 0;
+}
+
@@ -13038,10 +13384,6 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/ar
+ crashk_res.end - crashk_res.start + 1);
+#endif
+#endif
-+
-+ if (!xen_feature(XENFEAT_auto_translated_physmap))
-+ phys_to_machine_mapping =
-+ (unsigned long *)xen_start_info->mfn_list;
+}
+
+/*
@@ -13209,18 +13551,8 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/ar
+static void __init register_memory(void)
+{
+#ifdef CONFIG_XEN
-+ if (is_initial_xendomain()) {
-+ struct xen_memory_map memmap;
-+
-+ memmap.nr_entries = E820MAX;
-+ set_xen_guest_handle(memmap.buffer, machine_e820.map);
-+
-+ if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap))
-+ BUG();
-+
-+ machine_e820.nr_map = memmap.nr_entries;
++ if (is_initial_xendomain())
+ e820_setup_gap(machine_e820.map, machine_e820.nr_map);
-+ }
+ else
+#endif
+ e820_setup_gap(e820.map, e820.nr_map);
@@ -13263,6 +13595,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/ar
+ VMASST_TYPE_writable_pagetables));
+
+ memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
++ pre_setup_arch_hook();
+ early_cpu_init();
+#ifdef CONFIG_SMP
+ prefill_possible_map();
@@ -13316,8 +13649,6 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/ar
+ rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+
-+ setup_xen_features();
-+
+ ARCH_SETUP
+ if (efi_enabled)
+ efi_init();
@@ -13553,41 +13884,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/ar
+ * c-basic-offset:8
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/setup.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/setup.c
---- linux-2.6.18.8/arch/i386/kernel/setup.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/setup.c 2008-02-15 16:21:49.000000000 -0800
-@@ -956,6 +956,28 @@ efi_memory_present_wrapper(unsigned long
- return 0;
- }
-
-+/*
-+ * This function checks if any part of the range <start,end> is mapped
-+ * with type.
-+ */
-+int
-+e820_any_mapped(u64 start, u64 end, unsigned type)
-+{
-+ int i;
-+
-+ for (i = 0; i < e820.nr_map; i++) {
-+ const struct e820entry *ei = &e820.map[i];
-+
-+ if (type && ei->type != type)
-+ continue;
-+ if (ei->addr >= end || ei->addr + ei->size <= start)
-+ continue;
-+ return 1;
-+ }
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(e820_any_mapped);
-+
- /*
- * This function checks if the entire range <start,end> is mapped with type.
- *
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/smp-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/smp-xen.c
---- linux-2.6.18.8/arch/i386/kernel/smp-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/smp-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/smp-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/smp-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/smp-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/smp-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,605 @@
+/*
+ * Intel SMP support routines.
@@ -14194,9 +14493,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/smp-xen.c linux-2.6.18-xen-3.2.0/arch
+ return IRQ_HANDLED;
+}
+
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/sysenter.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/sysenter.c
---- linux-2.6.18.8/arch/i386/kernel/sysenter.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/sysenter.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/sysenter.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/sysenter.c
+--- linux-2.6.18.8/arch/i386/kernel/sysenter.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/sysenter.c 2008-08-21 11:36:07.000000000 +0200
@@ -23,6 +23,10 @@
#include <asm/pgtable.h>
#include <asm/unistd.h>
@@ -14254,10 +14553,36 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/sysenter.c linux-2.6.18-xen-3.2.0/arc
}
/*
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/time-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/time-xen.c
---- linux-2.6.18.8/arch/i386/kernel/time-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/time-xen.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,1194 @@
+@@ -75,11 +109,6 @@ int __init sysenter_setup(void)
+ #ifdef CONFIG_COMPAT_VDSO
+ __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY);
+ printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
+-#else
+- /*
+- * In the non-compat case the ELF coredumping code needs the fixmap:
+- */
+- __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_KERNEL_RO);
+ #endif
+
+ if (!boot_cpu_has(X86_FEATURE_SEP)) {
+@@ -142,6 +171,13 @@ int arch_setup_additional_pages(struct l
+ vma->vm_end = addr + PAGE_SIZE;
+ /* MAYWRITE to allow gdb to COW and set breakpoints */
+ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
++ /*
++ * Make sure the vDSO gets into every core dump.
++ * Dumping its contents makes post-mortem fully interpretable later
++ * without matching up the same kernel and hardware config to see
++ * what PC values meant.
++ */
++ vma->vm_flags |= VM_ALWAYSDUMP;
+ vma->vm_flags |= mm->def_flags;
+ vma->vm_page_prot = protection_map[vma->vm_flags & 7];
+ vma->vm_ops = &syscall_vm_ops;
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/time-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/time-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/time-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/time-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1209 @@
+/*
+ * linux/arch/i386/kernel/time.c
+ *
@@ -14397,13 +14722,21 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/time-xen.c linux-2.6.18-xen-3.2.0/arc
+}
+static DECLARE_WORK(clock_was_set_work, __clock_was_set, NULL);
+
++/*
++ * GCC 4.3 can turn loops over an induction variable into division. We do
++ * not support arbitrary 64-bit division, and so must break the induction.
++ */
++#define clobber_induction_variable(v) asm ( "" : "+r" (v) )
++
+static inline void __normalize_time(time_t *sec, s64 *nsec)
+{
+ while (*nsec >= NSEC_PER_SEC) {
++ clobber_induction_variable(*nsec);
+ (*nsec) -= NSEC_PER_SEC;
+ (*sec)++;
+ }
+ while (*nsec < 0) {
++ clobber_induction_variable(*nsec);
+ (*nsec) += NSEC_PER_SEC;
+ (*sec)--;
+ }
@@ -14566,21 +14899,28 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/time-xen.c linux-2.6.18-xen-3.2.0/arc
+{
+ struct vcpu_time_info *src;
+ struct shadow_time_info *dst;
++ unsigned long flags;
++ u32 pre_version, post_version;
+
+ src = &vcpu_info(cpu)->time;
+ dst = &per_cpu(shadow_time, cpu);
+
++ local_irq_save(flags);
++
+ do {
-+ dst->version = src->version;
++ pre_version = dst->version = src->version;
+ rmb();
+ dst->tsc_timestamp = src->tsc_timestamp;
+ dst->system_timestamp = src->system_time;
+ dst->tsc_to_nsec_mul = src->tsc_to_system_mul;
+ dst->tsc_shift = src->tsc_shift;
+ rmb();
-+ } while ((src->version & 1) | (dst->version ^ src->version));
++ post_version = src->version;
++ } while ((pre_version & 1) | (pre_version ^ post_version));
+
+ dst->tsc_to_usec_mul = dst->tsc_to_nsec_mul / 1000;
++
++ local_irq_restore(flags);
+}
+
+static inline int time_values_up_to_date(unsigned int cpu)
@@ -15265,7 +15605,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/time-xen.c linux-2.6.18-xen-3.2.0/arc
+ j = jiffies + 1;
+ }
+
-+ singleshot.timeout_abs_ns = jiffies_to_st(j);
++ singleshot.timeout_abs_ns = jiffies_to_st(j) + NS_PER_TICK/2;
+ singleshot.flags = 0;
+ rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot);
+#if CONFIG_XEN_COMPAT <= 0x030004
@@ -15452,9 +15792,32 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/time-xen.c linux-2.6.18-xen-3.2.0/arc
+ return 0;
+}
+__initcall(xen_sysctl_init);
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/traps-xen.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/traps-xen.c
---- linux-2.6.18.8/arch/i386/kernel/traps-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/traps-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/traps.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/traps.c
+--- linux-2.6.18.8/arch/i386/kernel/traps.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/traps.c 2008-08-21 11:36:07.000000000 +0200
+@@ -642,18 +642,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 -rpuN linux-2.6.18.8/arch/i386/kernel/traps-xen.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/traps-xen.c
+--- linux-2.6.18.8/arch/i386/kernel/traps-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/traps-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1190 @@
+/*
+ * linux/arch/i386/traps.c
@@ -16552,7 +16915,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/traps-xen.c linux-2.6.18-xen-3.2.0/ar
+ * NB. All these are "trap gates" (i.e. events_mask isn't set) except
+ * for those that specify <dpl>|4 in the second field.
+ */
-+static trap_info_t trap_table[] = {
++static trap_info_t __cpuinitdata trap_table[] = {
+ { 0, 0, __KERNEL_CS, (unsigned long)divide_error },
+ { 1, 0|4, __KERNEL_CS, (unsigned long)debug },
+ { 3, 3|4, __KERNEL_CS, (unsigned long)int3 },
@@ -16613,7 +16976,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/traps-xen.c linux-2.6.18-xen-3.2.0/ar
+ cpu_init();
+}
+
-+void smp_trap_init(trap_info_t *trap_ctxt)
++void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
+{
+ const trap_info_t *t = trap_table;
+
@@ -16646,32 +17009,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/traps-xen.c linux-2.6.18-xen-3.2.0/ar
+}
+__setup("call_trace=", call_trace_setup);
+#endif
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/traps.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/traps.c
---- linux-2.6.18.8/arch/i386/kernel/traps.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/traps.c 2008-02-15 16:21:49.000000000 -0800
-@@ -642,18 +642,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 -rpuN linux-2.6.18.8/arch/i386/kernel/vm86.c linux-2.6.18-xen-3.2.0/arch/i386/kernel/vm86.c
---- linux-2.6.18.8/arch/i386/kernel/vm86.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/vm86.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/vm86.c linux-2.6.18-xen-3.3.0/arch/i386/kernel/vm86.c
+--- linux-2.6.18.8/arch/i386/kernel/vm86.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/vm86.c 2008-08-21 11:36:07.000000000 +0200
@@ -97,7 +97,9 @@
struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
@@ -16726,9 +17066,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/vm86.c linux-2.6.18-xen-3.2.0/arch/i3
tsk->thread.screen_bitmap = info->screen_bitmap;
if (info->flags & VM86_SCREEN_BITMAP)
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/vmlinux.lds.S linux-2.6.18-xen-3.2.0/arch/i386/kernel/vmlinux.lds.S
---- linux-2.6.18.8/arch/i386/kernel/vmlinux.lds.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/vmlinux.lds.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/vmlinux.lds.S linux-2.6.18-xen-3.3.0/arch/i386/kernel/vmlinux.lds.S
+--- linux-2.6.18.8/arch/i386/kernel/vmlinux.lds.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/vmlinux.lds.S 2008-08-21 11:36:07.000000000 +0200
@@ -13,6 +13,12 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386"
OUTPUT_ARCH(i386)
ENTRY(phys_startup_32)
@@ -16771,9 +17111,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/vmlinux.lds.S linux-2.6.18-xen-3.2.0/
+
+ NOTES
}
-diff -rpuN linux-2.6.18.8/arch/i386/kernel/vsyscall-note-xen.S linux-2.6.18-xen-3.2.0/arch/i386/kernel/vsyscall-note-xen.S
---- linux-2.6.18.8/arch/i386/kernel/vsyscall-note-xen.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/kernel/vsyscall-note-xen.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/kernel/vsyscall-note-xen.S linux-2.6.18-xen-3.3.0/arch/i386/kernel/vsyscall-note-xen.S
+--- linux-2.6.18.8/arch/i386/kernel/vsyscall-note-xen.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/kernel/vsyscall-note-xen.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,32 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
@@ -16807,17 +17147,17 @@ diff -rpuN linux-2.6.18.8/arch/i386/kernel/vsyscall-note-xen.S linux-2.6.18-xen-
+NOTE_KERNELCAP_BEGIN(1, 1)
+NOTE_KERNELCAP(0, "nosegneg")
+NOTE_KERNELCAP_END
-diff -rpuN linux-2.6.18.8/arch/i386/lib/Makefile linux-2.6.18-xen-3.2.0/arch/i386/lib/Makefile
---- linux-2.6.18.8/arch/i386/lib/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/lib/Makefile 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/lib/Makefile linux-2.6.18-xen-3.3.0/arch/i386/lib/Makefile
+--- linux-2.6.18.8/arch/i386/lib/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/lib/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -7,3 +7,4 @@ lib-y = checksum.o delay.o usercopy.o ge
bitops.o
lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
+lib-$(CONFIG_XEN_SCRUB_PAGES) += scrub.o
-diff -rpuN linux-2.6.18.8/arch/i386/lib/scrub.c linux-2.6.18-xen-3.2.0/arch/i386/lib/scrub.c
---- linux-2.6.18.8/arch/i386/lib/scrub.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/lib/scrub.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/lib/scrub.c linux-2.6.18-xen-3.3.0/arch/i386/lib/scrub.c
+--- linux-2.6.18.8/arch/i386/lib/scrub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/lib/scrub.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,21 @@
+#include <asm/cpufeature.h>
+#include <asm/page.h>
@@ -16840,23 +17180,24 @@ diff -rpuN linux-2.6.18.8/arch/i386/lib/scrub.c linux-2.6.18-xen-3.2.0/arch/i386
+ for (; count--; v += PAGE_SIZE)
+ clear_page(v);
+}
-diff -rpuN linux-2.6.18.8/arch/i386/mach-xen/Makefile linux-2.6.18-xen-3.2.0/arch/i386/mach-xen/Makefile
---- linux-2.6.18.8/arch/i386/mach-xen/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mach-xen/Makefile 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/mach-xen/Makefile linux-2.6.18-xen-3.3.0/arch/i386/mach-xen/Makefile
+--- linux-2.6.18.8/arch/i386/mach-xen/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mach-xen/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := setup.o
-diff -rpuN linux-2.6.18.8/arch/i386/mach-xen/setup.c linux-2.6.18-xen-3.2.0/arch/i386/mach-xen/setup.c
---- linux-2.6.18.8/arch/i386/mach-xen/setup.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mach-xen/setup.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,147 @@
+diff -rpuN linux-2.6.18.8/arch/i386/mach-xen/setup.c linux-2.6.18-xen-3.3.0/arch/i386/mach-xen/setup.c
+--- linux-2.6.18.8/arch/i386/mach-xen/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mach-xen/setup.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,158 @@
+/*
+ * Machine specific setup for generic
+ */
+
++#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
@@ -16942,17 +17283,39 @@ diff -rpuN linux-2.6.18.8/arch/i386/mach-xen/setup.c linux-2.6.18-xen-3.2.0/arch
+extern void failsafe_callback(void);
+extern void nmi(void);
+
-+unsigned long *machine_to_phys_mapping;
++unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
+EXPORT_SYMBOL(machine_to_phys_mapping);
+unsigned int machine_to_phys_order;
+EXPORT_SYMBOL(machine_to_phys_order);
+
-+void __init machine_specific_arch_setup(void)
++void __init pre_setup_arch_hook(void)
+{
-+ int ret;
+ struct xen_machphys_mapping mapping;
+ unsigned long machine_to_phys_nr_ents;
+ struct xen_platform_parameters pp;
++
++ init_mm.pgd = swapper_pg_dir = (pgd_t *)xen_start_info->pt_base;
++
++ setup_xen_features();
++
++ if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0)
++ set_fixaddr_top(pp.virt_start);
++
++ if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
++ machine_to_phys_mapping = (unsigned long *)mapping.v_start;
++ machine_to_phys_nr_ents = mapping.max_mfn + 1;
++ } else
++ machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
++ machine_to_phys_order = fls(machine_to_phys_nr_ents - 1);
++
++ if (!xen_feature(XENFEAT_auto_translated_physmap))
++ phys_to_machine_mapping =
++ (unsigned long *)xen_start_info->mfn_list;
++}
++
++void __init machine_specific_arch_setup(void)
++{
++ int ret;
+ static struct callback_register __initdata event = {
+ .type = CALLBACKTYPE_event,
+ .address = { __KERNEL_CS, (unsigned long)hypervisor_callback },
@@ -16987,30 +17350,54 @@ diff -rpuN linux-2.6.18.8/arch/i386/mach-xen/setup.c linux-2.6.18-xen-3.2.0/arch
+ HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+ }
+#endif
++}
+diff -rpuN linux-2.6.18.8/arch/i386/Makefile linux-2.6.18-xen-3.3.0/arch/i386/Makefile
+--- linux-2.6.18.8/arch/i386/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -71,6 +71,10 @@ mcore-$(CONFIG_X86_BIGSMP) := mach-defau
+ mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit
+ mcore-$(CONFIG_X86_SUMMIT) := mach-default
+
++# Xen subarch support
++mflags-$(CONFIG_X86_XEN) := -Iinclude/asm-i386/mach-xen
++mcore-$(CONFIG_X86_XEN) := mach-xen
+
-+ if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0)
-+ set_fixaddr_top(pp.virt_start);
+ # generic subarchitecture
+ mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic
+ mcore-$(CONFIG_X86_GENERICARCH) := mach-default
+@@ -102,9 +106,20 @@ AFLAGS += $(mflags-y)
+
+ boot := arch/i386/boot
+
+-PHONY += zImage bzImage compressed zlilo bzlilo \
++PHONY += zImage bzImage vmlinuz compressed zlilo bzlilo \
+ zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install
+
++ifdef CONFIG_XEN
++CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
++ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS)
++all: vmlinuz
+
-+ machine_to_phys_mapping = (unsigned long *)MACH2PHYS_VIRT_START;
-+ machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
-+ if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
-+ machine_to_phys_mapping = (unsigned long *)mapping.v_start;
-+ machine_to_phys_nr_ents = mapping.max_mfn + 1;
-+ }
-+ while ((1UL << machine_to_phys_order) < machine_to_phys_nr_ents )
-+ machine_to_phys_order++;
-+}
-diff -rpuN linux-2.6.18.8/arch/i386/mm/Makefile linux-2.6.18-xen-3.2.0/arch/i386/mm/Makefile
---- linux-2.6.18.8/arch/i386/mm/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -8,3 +8,4 @@ obj-$(CONFIG_NUMA) += discontig.o
- obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
- obj-$(CONFIG_HIGHMEM) += highmem.o
- obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o
-+obj-$(CONFIG_XEN) += hypervisor.o
-diff -rpuN linux-2.6.18.8/arch/i386/mm/fault-xen.c linux-2.6.18-xen-3.2.0/arch/i386/mm/fault-xen.c
---- linux-2.6.18.8/arch/i386/mm/fault-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/fault-xen.c 2008-02-15 16:21:49.000000000 -0800
++# KBUILD_IMAGE specifies the target image being built
++KBUILD_IMAGE := $(boot)/vmlinuz
++
++vmlinuz: vmlinux
++ $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
++else
+ all: bzImage
+
+ # KBUILD_IMAGE specify target image being built
+@@ -124,6 +139,7 @@ zdisk bzdisk: vmlinux
+
+ fdimage fdimage144 fdimage288 isoimage: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
++endif
+
+ install:
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
+diff -rpuN linux-2.6.18.8/arch/i386/mm/fault-xen.c linux-2.6.18-xen-3.3.0/arch/i386/mm/fault-xen.c
+--- linux-2.6.18.8/arch/i386/mm/fault-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/fault-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,779 @@
+/*
+ * linux/arch/i386/mm/fault.c
@@ -17791,9 +18178,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/fault-xen.c linux-2.6.18-xen-3.2.0/arch/i
+ }
+}
+#endif
-diff -rpuN linux-2.6.18.8/arch/i386/mm/highmem-xen.c linux-2.6.18-xen-3.2.0/arch/i386/mm/highmem-xen.c
---- linux-2.6.18.8/arch/i386/mm/highmem-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/highmem-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/mm/highmem-xen.c linux-2.6.18-xen-3.3.0/arch/i386/mm/highmem-xen.c
+--- linux-2.6.18.8/arch/i386/mm/highmem-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/highmem-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,136 @@
+#include <linux/highmem.h>
+#include <linux/module.h>
@@ -17931,9 +18318,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/highmem-xen.c linux-2.6.18-xen-3.2.0/arch
+EXPORT_SYMBOL(kmap_atomic_pte);
+EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_to_page);
-diff -rpuN linux-2.6.18.8/arch/i386/mm/hypervisor.c linux-2.6.18-xen-3.2.0/arch/i386/mm/hypervisor.c
---- linux-2.6.18.8/arch/i386/mm/hypervisor.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/hypervisor.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/mm/hypervisor.c linux-2.6.18-xen-3.3.0/arch/i386/mm/hypervisor.c
+--- linux-2.6.18.8/arch/i386/mm/hypervisor.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/hypervisor.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,602 @@
+/******************************************************************************
+ * mm/hypervisor.c
@@ -18537,10 +18924,10 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/hypervisor.c linux-2.6.18-xen-3.2.0/arch/
+ BUG_ON(rc && rc != -ENOSYS);
+ return !rc;
+}
-diff -rpuN linux-2.6.18.8/arch/i386/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/i386/mm/init-xen.c
---- linux-2.6.18.8/arch/i386/mm/init-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/init-xen.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,850 @@
+diff -rpuN linux-2.6.18.8/arch/i386/mm/init-xen.c linux-2.6.18-xen-3.3.0/arch/i386/mm/init-xen.c
+--- linux-2.6.18.8/arch/i386/mm/init-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/init-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,847 @@
+/*
+ * linux/arch/i386/mm/init.c
+ *
@@ -18931,9 +19318,6 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/i3
+ unsigned long vaddr;
+ pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
+
-+ swapper_pg_dir = pgd_base;
-+ init_mm.pgd = pgd_base;
-+
+ /* Enable PSE if available */
+ if (cpu_has_pse) {
+ set_in_cr4(X86_CR4_PSE);
@@ -19391,9 +19775,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/i3
+}
+#endif
+
-diff -rpuN linux-2.6.18.8/arch/i386/mm/ioremap-xen.c linux-2.6.18-xen-3.2.0/arch/i386/mm/ioremap-xen.c
---- linux-2.6.18.8/arch/i386/mm/ioremap-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/ioremap-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/mm/ioremap-xen.c linux-2.6.18-xen-3.3.0/arch/i386/mm/ioremap-xen.c
+--- linux-2.6.18.8/arch/i386/mm/ioremap-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/ioremap-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,443 @@
+/*
+ * arch/i386/mm/ioremap.c
@@ -19473,7 +19857,7 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/ioremap-xen.c linux-2.6.18-xen-3.2.0/arch
+ * Fill in the machine address: PTE ptr is done later by
+ * apply_to_page_range().
+ */
-+ v->val = __pte_val(pfn_pte_ma(mfn, prot));
++ v->val = __pte_val(pfn_pte_ma(mfn, prot)) | _PAGE_IO;
+
+ mfn++;
+ address += PAGE_SIZE;
@@ -19838,9 +20222,17 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/ioremap-xen.c linux-2.6.18-xen-3.2.0/arch
+ --nrpages;
+ }
+}
-diff -rpuN linux-2.6.18.8/arch/i386/mm/pageattr.c linux-2.6.18-xen-3.2.0/arch/i386/mm/pageattr.c
---- linux-2.6.18.8/arch/i386/mm/pageattr.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/pageattr.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/mm/Makefile linux-2.6.18-xen-3.3.0/arch/i386/mm/Makefile
+--- linux-2.6.18.8/arch/i386/mm/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -8,3 +8,4 @@ obj-$(CONFIG_NUMA) += discontig.o
+ obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+ obj-$(CONFIG_HIGHMEM) += highmem.o
+ obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o
++obj-$(CONFIG_XEN) += hypervisor.o
+diff -rpuN linux-2.6.18.8/arch/i386/mm/pageattr.c linux-2.6.18-xen-3.3.0/arch/i386/mm/pageattr.c
+--- linux-2.6.18.8/arch/i386/mm/pageattr.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/pageattr.c 2008-08-21 11:36:07.000000000 +0200
@@ -84,7 +84,7 @@ static void set_pmd_pte(pte_t *kpte, uns
unsigned long flags;
@@ -19850,9 +20242,117 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/pageattr.c linux-2.6.18-xen-3.2.0/arch/i3
return;
spin_lock_irqsave(&pgd_lock, flags);
-diff -rpuN linux-2.6.18.8/arch/i386/mm/pgtable-xen.c linux-2.6.18-xen-3.2.0/arch/i386/mm/pgtable-xen.c
---- linux-2.6.18.8/arch/i386/mm/pgtable-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/pgtable-xen.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/mm/pgtable.c linux-2.6.18-xen-3.3.0/arch/i386/mm/pgtable.c
+--- linux-2.6.18.8/arch/i386/mm/pgtable.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/pgtable.c 2008-08-21 11:36:07.000000000 +0200
+@@ -12,6 +12,7 @@
+ #include <linux/slab.h>
+ #include <linux/pagemap.h>
+ #include <linux/spinlock.h>
++#include <linux/module.h>
+
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -137,6 +138,10 @@ void set_pmd_pfn(unsigned long vaddr, un
+ __flush_tlb_one(vaddr);
+ }
+
++static int nr_fixmaps = 0;
++unsigned long __FIXADDR_TOP = 0xfffff000;
++EXPORT_SYMBOL(__FIXADDR_TOP);
++
+ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
+ {
+ unsigned long address = __fix_to_virt(idx);
+@@ -146,6 +151,13 @@ void __set_fixmap (enum fixed_addresses
+ return;
+ }
+ set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
++ nr_fixmaps++;
++}
++
++void set_fixaddr_top(unsigned long top)
++{
++ BUG_ON(nr_fixmaps > 0);
++ __FIXADDR_TOP = top - PAGE_SIZE;
+ }
+
+ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+@@ -214,9 +226,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;
+
+@@ -248,6 +261,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:
+@@ -262,9 +299,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 -rpuN linux-2.6.18.8/arch/i386/mm/pgtable-xen.c linux-2.6.18-xen-3.3.0/arch/i386/mm/pgtable-xen.c
+--- linux-2.6.18.8/arch/i386/mm/pgtable-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/mm/pgtable-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,725 @@
+/*
+ * linux/arch/i386/mm/pgtable.c
@@ -20579,117 +21079,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/mm/pgtable-xen.c linux-2.6.18-xen-3.2.0/arch
+ !mm->context.has_foreign_mappings)
+ mm_unpin(mm);
+}
-diff -rpuN linux-2.6.18.8/arch/i386/mm/pgtable.c linux-2.6.18-xen-3.2.0/arch/i386/mm/pgtable.c
---- linux-2.6.18.8/arch/i386/mm/pgtable.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/mm/pgtable.c 2008-02-15 16:21:49.000000000 -0800
-@@ -12,6 +12,7 @@
- #include <linux/slab.h>
- #include <linux/pagemap.h>
- #include <linux/spinlock.h>
-+#include <linux/module.h>
-
- #include <asm/system.h>
- #include <asm/pgtable.h>
-@@ -137,6 +138,10 @@ void set_pmd_pfn(unsigned long vaddr, un
- __flush_tlb_one(vaddr);
- }
-
-+static int nr_fixmaps = 0;
-+unsigned long __FIXADDR_TOP = 0xfffff000;
-+EXPORT_SYMBOL(__FIXADDR_TOP);
-+
- void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
- {
- unsigned long address = __fix_to_virt(idx);
-@@ -146,6 +151,13 @@ void __set_fixmap (enum fixed_addresses
- return;
- }
- set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
-+ nr_fixmaps++;
-+}
-+
-+void set_fixaddr_top(unsigned long top)
-+{
-+ BUG_ON(nr_fixmaps > 0);
-+ __FIXADDR_TOP = top - PAGE_SIZE;
- }
-
- pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-@@ -214,9 +226,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;
-
-@@ -248,6 +261,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:
-@@ -262,9 +299,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 -rpuN linux-2.6.18.8/arch/i386/oprofile/Makefile linux-2.6.18-xen-3.2.0/arch/i386/oprofile/Makefile
---- linux-2.6.18.8/arch/i386/oprofile/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/oprofile/Makefile 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/oprofile/Makefile linux-2.6.18-xen-3.3.0/arch/i386/oprofile/Makefile
+--- linux-2.6.18.8/arch/i386/oprofile/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/oprofile/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -6,7 +6,14 @@ DRIVER_OBJS = $(addprefix ../../../drive
oprofilefs.o oprofile_stats.o \
timer_int.o )
@@ -20705,9 +21097,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/oprofile/Makefile linux-2.6.18-xen-3.2.0/arc
op_model_ppro.o op_model_p4.o
oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o
+endif
-diff -rpuN linux-2.6.18.8/arch/i386/oprofile/xenoprof.c linux-2.6.18-xen-3.2.0/arch/i386/oprofile/xenoprof.c
---- linux-2.6.18.8/arch/i386/oprofile/xenoprof.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/oprofile/xenoprof.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/oprofile/xenoprof.c linux-2.6.18-xen-3.3.0/arch/i386/oprofile/xenoprof.c
+--- linux-2.6.18.8/arch/i386/oprofile/xenoprof.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/oprofile/xenoprof.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,179 @@
+/**
+ * @file xenoprof.c
@@ -20888,24 +21280,30 @@ diff -rpuN linux-2.6.18.8/arch/i386/oprofile/xenoprof.c linux-2.6.18-xen-3.2.0/a
+{
+ xenoprofile_exit();
+}
-diff -rpuN linux-2.6.18.8/arch/i386/pci/Makefile linux-2.6.18-xen-3.2.0/arch/i386/pci/Makefile
---- linux-2.6.18.8/arch/i386/pci/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/pci/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -4,6 +4,10 @@ obj-$(CONFIG_PCI_BIOS) += pcbios.o
- obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
- obj-$(CONFIG_PCI_DIRECT) += direct.o
-
-+# pcifront should be after pcbios.o, mmconfig.o, and direct.o as it should only
-+# take over if direct access to the PCI bus is unavailable
-+obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront.o
-+
- pci-y := fixup.o
- pci-$(CONFIG_ACPI) += acpi.o
- pci-y += legacy.o irq.o
-diff -rpuN linux-2.6.18.8/arch/i386/pci/irq-xen.c linux-2.6.18-xen-3.2.0/arch/i386/pci/irq-xen.c
---- linux-2.6.18.8/arch/i386/pci/irq-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/pci/irq-xen.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,1205 @@
+diff -rpuN linux-2.6.18.8/arch/i386/pci/irq.c linux-2.6.18-xen-3.3.0/arch/i386/pci/irq.c
+--- linux-2.6.18.8/arch/i386/pci/irq.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/pci/irq.c 2008-08-21 11:36:07.000000000 +0200
+@@ -543,6 +543,16 @@ static __init int intel_router_probe(str
+ case PCI_DEVICE_ID_INTEL_ICH8_2:
+ case PCI_DEVICE_ID_INTEL_ICH8_3:
+ case PCI_DEVICE_ID_INTEL_ICH8_4:
++ case PCI_DEVICE_ID_INTEL_ICH9_0:
++ case PCI_DEVICE_ID_INTEL_ICH9_1:
++ case PCI_DEVICE_ID_INTEL_ICH9_2:
++ case PCI_DEVICE_ID_INTEL_ICH9_3:
++ case PCI_DEVICE_ID_INTEL_ICH9_4:
++ case PCI_DEVICE_ID_INTEL_ICH9_5:
++ case PCI_DEVICE_ID_INTEL_ICH10_0:
++ case PCI_DEVICE_ID_INTEL_ICH10_1:
++ case PCI_DEVICE_ID_INTEL_ICH10_2:
++ case PCI_DEVICE_ID_INTEL_ICH10_3:
+ r->name = "PIIX/ICH";
+ r->get = pirq_piix_get;
+ r->set = pirq_piix_set;
+diff -rpuN linux-2.6.18.8/arch/i386/pci/irq-xen.c linux-2.6.18-xen-3.3.0/arch/i386/pci/irq-xen.c
+--- linux-2.6.18.8/arch/i386/pci/irq-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/pci/irq-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1215 @@
+/*
+ * Low-Level PCI Support for PC -- Routing of Interrupts
+ *
@@ -21167,13 +21565,13 @@ diff -rpuN linux-2.6.18.8/arch/i386/pci/irq-xen.c linux-2.6.18-xen-3.2.0/arch/i3
+ */
+static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
-+ static const unsigned int pirqmap[4] = { 3, 2, 5, 1 };
++ static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+ return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
+}
+
+static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
-+ static const unsigned int pirqmap[4] = { 3, 2, 5, 1 };
++ static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+ write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+ return 1;
+}
@@ -21455,6 +21853,16 @@ diff -rpuN linux-2.6.18.8/arch/i386/pci/irq-xen.c linux-2.6.18-xen-3.2.0/arch/i3
+ case PCI_DEVICE_ID_INTEL_ICH8_2:
+ case PCI_DEVICE_ID_INTEL_ICH8_3:
+ case PCI_DEVICE_ID_INTEL_ICH8_4:
++ case PCI_DEVICE_ID_INTEL_ICH9_0:
++ case PCI_DEVICE_ID_INTEL_ICH9_1:
++ case PCI_DEVICE_ID_INTEL_ICH9_2:
++ case PCI_DEVICE_ID_INTEL_ICH9_3:
++ case PCI_DEVICE_ID_INTEL_ICH9_4:
++ case PCI_DEVICE_ID_INTEL_ICH9_5:
++ case PCI_DEVICE_ID_INTEL_ICH10_0:
++ case PCI_DEVICE_ID_INTEL_ICH10_1:
++ case PCI_DEVICE_ID_INTEL_ICH10_2:
++ case PCI_DEVICE_ID_INTEL_ICH10_3:
+ r->name = "PIIX/ICH";
+ r->get = pirq_piix_get;
+ r->set = pirq_piix_set;
@@ -22111,25 +22519,23 @@ diff -rpuN linux-2.6.18.8/arch/i386/pci/irq-xen.c linux-2.6.18-xen-3.2.0/arch/i3
+
+ return count;
+}
-diff -rpuN linux-2.6.18.8/arch/i386/pci/irq.c linux-2.6.18-xen-3.2.0/arch/i386/pci/irq.c
---- linux-2.6.18.8/arch/i386/pci/irq.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/pci/irq.c 2008-02-15 16:21:49.000000000 -0800
-@@ -543,6 +543,12 @@ static __init int intel_router_probe(str
- case PCI_DEVICE_ID_INTEL_ICH8_2:
- case PCI_DEVICE_ID_INTEL_ICH8_3:
- case PCI_DEVICE_ID_INTEL_ICH8_4:
-+ case PCI_DEVICE_ID_INTEL_ICH9_0:
-+ case PCI_DEVICE_ID_INTEL_ICH9_1:
-+ case PCI_DEVICE_ID_INTEL_ICH9_2:
-+ case PCI_DEVICE_ID_INTEL_ICH9_3:
-+ case PCI_DEVICE_ID_INTEL_ICH9_4:
-+ case PCI_DEVICE_ID_INTEL_ICH9_5:
- r->name = "PIIX/ICH";
- r->get = pirq_piix_get;
- r->set = pirq_piix_set;
-diff -rpuN linux-2.6.18.8/arch/i386/pci/pcifront.c linux-2.6.18-xen-3.2.0/arch/i386/pci/pcifront.c
---- linux-2.6.18.8/arch/i386/pci/pcifront.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/pci/pcifront.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/pci/Makefile linux-2.6.18-xen-3.3.0/arch/i386/pci/Makefile
+--- linux-2.6.18.8/arch/i386/pci/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/pci/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -4,6 +4,10 @@ obj-$(CONFIG_PCI_BIOS) += pcbios.o
+ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
+ obj-$(CONFIG_PCI_DIRECT) += direct.o
+
++# pcifront should be after pcbios.o, mmconfig.o, and direct.o as it should only
++# take over if direct access to the PCI bus is unavailable
++obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront.o
++
+ pci-y := fixup.o
+ pci-$(CONFIG_ACPI) += acpi.o
+ pci-y += legacy.o irq.o
+diff -rpuN linux-2.6.18.8/arch/i386/pci/pcifront.c linux-2.6.18-xen-3.3.0/arch/i386/pci/pcifront.c
+--- linux-2.6.18.8/arch/i386/pci/pcifront.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/pci/pcifront.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,55 @@
+/*
+ * PCI Frontend Stub - puts some "dummy" functions in to the Linux x86 PCI core
@@ -22186,18 +22592,9 @@ diff -rpuN linux-2.6.18.8/arch/i386/pci/pcifront.c linux-2.6.18-xen-3.2.0/arch/i
+}
+
+arch_initcall(pcifront_x86_stub_init);
-diff -rpuN linux-2.6.18.8/arch/i386/power/Makefile linux-2.6.18-xen-3.2.0/arch/i386/power/Makefile
---- linux-2.6.18.8/arch/i386/power/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/power/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -1,2 +1,4 @@
--obj-$(CONFIG_PM) += cpu.o
-+obj-$(subst m,y,$(CONFIG_APM)) += cpu.o
-+obj-$(CONFIG_SOFTWARE_SUSPEND) += cpu.o
-+obj-$(CONFIG_ACPI_SLEEP) += cpu.o
- obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
-diff -rpuN linux-2.6.18.8/arch/i386/power/cpu.c linux-2.6.18-xen-3.2.0/arch/i386/power/cpu.c
---- linux-2.6.18.8/arch/i386/power/cpu.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/i386/power/cpu.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/power/cpu.c linux-2.6.18-xen-3.3.0/arch/i386/power/cpu.c
+--- linux-2.6.18.8/arch/i386/power/cpu.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/power/cpu.c 2008-08-21 11:36:07.000000000 +0200
@@ -62,11 +62,12 @@ static void do_fpu_end(void)
static void fix_processor_context(void)
@@ -22212,158 +22609,18 @@ diff -rpuN linux-2.6.18.8/arch/i386/power/cpu.c linux-2.6.18-xen-3.2.0/arch/i386
load_TR_desc(); /* This does ltr */
load_LDT(&current->active_mm->context); /* This does lldt */
-diff -rpuN linux-2.6.18.8/arch/ia64/Kconfig linux-2.6.18-xen-3.2.0/arch/ia64/Kconfig
---- linux-2.6.18.8/arch/ia64/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/Kconfig 2008-02-15 16:21:49.000000000 -0800
-@@ -58,6 +58,28 @@ config GENERIC_IOMAP
- bool
- default y
-
-+config XEN
-+ bool "Xen hypervisor support"
-+ default y
-+ select XEN_XENCOMM
-+ help
-+ Enable Xen hypervisor support. Resulting kernel runs
-+ both as a guest OS on Xen and natively on hardware.
-+
-+config XEN_IA64_EXPOSE_P2M
-+ bool "Xen/IA64 exposure p2m table"
-+ depends on XEN
-+ default y
-+ help
-+ expose p2m from xen
-+
-+config XEN_IA64_EXPOSE_P2M_USE_DTR
-+ bool "Xen/IA64 map p2m table with dtr"
-+ depends on XEN_IA64_EXPOSE_P2M
-+ default y
-+ help
-+ use dtr to map the exposed p2m table
-+
- config SCHED_NO_NO_OMIT_FRAME_POINTER
- bool
- default y
-@@ -133,6 +155,10 @@ config IA64_SGI_SN2
- config IA64_HP_SIM
- bool "Ski-simulator"
-
-+config IA64_XEN
-+ bool "Xen guest"
-+ depends on XEN
-+
- endchoice
-
- choice
-@@ -431,6 +457,29 @@ config SGI_SN
-
- source "drivers/sn/Kconfig"
-
-+config KEXEC
-+ bool "kexec system call (EXPERIMENTAL)"
-+ depends on EXPERIMENTAL && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
-+ help
-+ kexec is a system call that implements the ability to shutdown your
-+ current kernel, and to start another kernel. It is like a reboot
-+ but it is indepedent of the system firmware. And like a reboot
-+ you can start any kernel with it, not just Linux.
-+
-+ The name comes from the similiarity to the exec system call.
-+
-+ It is an ongoing process to be certain the hardware in a machine
-+ is properly shutdown, so do not be surprised if this code does not
-+ initially work for you. It may help to enable device hotplugging
-+ support. As of this writing the exact hardware interface is
-+ strongly in flux, so no good recommendation can be made.
-+
-+config CRASH_DUMP
-+ bool "kernel crash dumps (EXPERIMENTAL)"
-+ depends on EXPERIMENTAL && IA64_MCA_RECOVERY && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
-+ help
-+ Generate crash dump after being started by kexec.
-+
- source "drivers/firmware/Kconfig"
-
- source "fs/Kconfig.binfmt"
-@@ -465,6 +514,21 @@ config PCI_DOMAINS
- bool
- default PCI
-
-+config XEN_PCIDEV_FRONTEND
-+ bool "Xen PCI Frontend"
-+ depends on PCI && XEN
-+ default y
-+ help
-+ The PCI device frontend driver allows the kernel to import arbitrary
-+ PCI devices from a PCI backend to support PCI driver domains.
-+
-+config XEN_PCIDEV_FE_DEBUG
-+ bool "Xen PCI Frontend Debugging"
-+ depends on XEN_PCIDEV_FRONTEND
-+ default n
-+ help
-+ Enables some debug statements within the PCI Frontend.
-+
- source "drivers/pci/pcie/Kconfig"
-
- source "drivers/pci/Kconfig"
-@@ -528,3 +592,16 @@ source "arch/ia64/Kconfig.debug"
- source "security/Kconfig"
-
- source "crypto/Kconfig"
-+
-+#
-+# override default values of drivers/xen/Kconfig
-+#
-+if XEN
-+config XEN_SMPBOOT
-+ default n
-+
-+config XEN_DEVMEM
-+ default n
-+endif
-+
-+source "drivers/xen/Kconfig"
-diff -rpuN linux-2.6.18.8/arch/ia64/Makefile linux-2.6.18-xen-3.2.0/arch/ia64/Makefile
---- linux-2.6.18.8/arch/ia64/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -45,6 +45,12 @@ ifeq ($(call cc-version),0304)
- endif
-
- CFLAGS += $(cflags-y)
-+
-+cppflags-$(CONFIG_XEN) += \
-+ -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION)
-+
-+CPPFLAGS += $(cppflags-y)
-+
- head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
-
- libs-y += arch/ia64/lib/
-@@ -54,7 +60,9 @@ core-$(CONFIG_IA64_DIG) += arch/ia64/di
- core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
- core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
- core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
-+core-$(CONFIG_IA64_XEN) += arch/ia64/dig/
- core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/
-+core-$(CONFIG_XEN) += arch/ia64/xen/
-
- drivers-$(CONFIG_PCI) += arch/ia64/pci/
- drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
-@@ -87,8 +95,8 @@ CLEAN_FILES += vmlinux.gz bootloader
- boot: lib/lib.a vmlinux
- $(Q)$(MAKE) $(build)=$(boot) $@
-
--install: vmlinux.gz
-- sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
-+install:
-+ -yes | sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
-
- define archhelp
- echo '* compressed - Build compressed kernel image'
-diff -rpuN linux-2.6.18.8/arch/ia64/hp/common/sba_iommu.c linux-2.6.18-xen-3.2.0/arch/ia64/hp/common/sba_iommu.c
---- linux-2.6.18.8/arch/ia64/hp/common/sba_iommu.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/hp/common/sba_iommu.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/i386/power/Makefile linux-2.6.18-xen-3.3.0/arch/i386/power/Makefile
+--- linux-2.6.18.8/arch/i386/power/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/i386/power/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -1,2 +1,4 @@
+-obj-$(CONFIG_PM) += cpu.o
++obj-$(subst m,y,$(CONFIG_APM)) += cpu.o
++obj-$(CONFIG_SOFTWARE_SUSPEND) += cpu.o
++obj-$(CONFIG_ACPI_SLEEP) += cpu.o
+ obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
+diff -rpuN linux-2.6.18.8/arch/ia64/hp/common/sba_iommu.c linux-2.6.18-xen-3.3.0/arch/ia64/hp/common/sba_iommu.c
+--- linux-2.6.18.8/arch/ia64/hp/common/sba_iommu.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/hp/common/sba_iommu.c 2008-08-21 11:36:07.000000000 +0200
@@ -42,6 +42,11 @@
#include <asm/system.h> /* wmb() */
@@ -22701,83 +22958,121 @@ diff -rpuN linux-2.6.18.8/arch/ia64/hp/common/sba_iommu.c linux-2.6.18-xen-3.2.0
DBG_INIT("%s() prefetch spill addr: 0x%lx\n", __FUNCTION__, prefetch_spill_page);
}
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/Makefile linux-2.6.18-xen-3.2.0/arch/ia64/kernel/Makefile
---- linux-2.6.18.8/arch/ia64/kernel/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -28,6 +28,8 @@ obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
- obj-$(CONFIG_CPU_FREQ) += cpufreq/
- obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
- obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
-+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
-+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
- obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
- obj-$(CONFIG_AUDIT) += audit.o
- mca_recovery-y += mca_drv.o mca_drv_asm.o
-@@ -61,3 +63,61 @@ $(obj)/gate-syms.o: $(obj)/gate.lds $(ob
- # We must build gate.so before we can assemble it.
- # Note: kbuild does not track this dependency due to usage of .incbin
- $(obj)/gate-data.o: $(obj)/gate.so
+diff -rpuN linux-2.6.18.8/arch/ia64/Kconfig linux-2.6.18-xen-3.3.0/arch/ia64/Kconfig
+--- linux-2.6.18.8/arch/ia64/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -58,6 +58,28 @@ config GENERIC_IOMAP
+ bool
+ default y
+
++config XEN
++ bool "Xen hypervisor support"
++ default y
++ select XEN_XENCOMM
++ help
++ Enable Xen hypervisor support. Resulting kernel runs
++ both as a guest OS on Xen and natively on hardware.
+
-+#
-+# gate page paravirtualization for xen
-+#
-+obj-$(CONFIG_XEN) += xengate-data.o
++config XEN_IA64_EXPOSE_P2M
++ bool "Xen/IA64 exposure p2m table"
++ depends on XEN
++ default y
++ help
++ expose p2m from xen
+
-+ifeq ($(CONFIG_XEN), y)
-+# The gate DSO image is built using a special linker script.
-+targets += xengate.so xengate-syms.o
-+endif
++config XEN_IA64_EXPOSE_P2M_USE_DTR
++ bool "Xen/IA64 map p2m table with dtr"
++ depends on XEN_IA64_EXPOSE_P2M
++ default y
++ help
++ use dtr to map the exposed p2m table
+
-+extra-$(CONFIG_XEN) += xengate.so xengate.lds xengate.o
+ config SCHED_NO_NO_OMIT_FRAME_POINTER
+ bool
+ default y
+@@ -133,6 +155,10 @@ config IA64_SGI_SN2
+ config IA64_HP_SIM
+ bool "Ski-simulator"
+
++config IA64_XEN
++ bool "Xen guest"
++ depends on XEN
+
-+AFLAGS_xengate.o += -D__XEN_IA64_VDSO_PARAVIRT
-+$(obj)/xengate.o: $(src)/gate.S FORCE
-+ $(call if_changed_dep,as_o_S)
+ endchoice
+
+ choice
+@@ -431,6 +457,29 @@ config SGI_SN
+
+ source "drivers/sn/Kconfig"
+
++config KEXEC
++ bool "kexec system call (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU) && !XEN_UNPRIVILEGED_GUEST
++ help
++ kexec is a system call that implements the ability to shutdown your
++ current kernel, and to start another kernel. It is like a reboot
++ but it is indepedent of the system firmware. And like a reboot
++ you can start any kernel with it, not just Linux.
+
-+CPPFLAGS_xengate.lds := -P -C -U$(ARCH) -D__XEN_IA64_VDSO_PARAVIRT
-+$(obj)/xengate.lds: $(src)/gate.lds.S
-+ $(call if_changed_dep,cpp_lds_S)
++ The name comes from the similiarity to the exec system call.
+
-+GATECFLAGS_xengate.so = -shared -s -Wl,-soname=linux-gate.so.1 \
-+ $(call ld-option, -Wl$(comma)--hash-style=sysv)
-+$(obj)/xengate.so: $(obj)/xengate.lds $(obj)/xengate.o FORCE
-+ $(call if_changed,gate)
++ It is an ongoing process to be certain the hardware in a machine
++ is properly shutdown, so do not be surprised if this code does not
++ initially work for you. It may help to enable device hotplugging
++ support. As of this writing the exact hardware interface is
++ strongly in flux, so no good recommendation can be made.
+
-+ifeq ($(CONFIG_XEN), y)
-+$(obj)/built-in.o: $(obj)/xengate-syms.o
-+$(obj)/built-in.o: ld_flags += -R $(obj)/xengate-syms.o
-+$(obj)/mca_recovery.o: $(obj)/gate-syms.o $(obj)/xengate-syms.o
-+endif
++config CRASH_DUMP
++ bool "kernel crash dumps (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && IA64_MCA_RECOVERY && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
++ help
++ Generate crash dump after being started by kexec.
+
-+GATECFLAGS_xengate-syms.o = -r
-+$(obj)/xengate-syms.o: $(obj)/xengate.lds $(obj)/xengate.o FORCE
-+ $(call if_changed,gate)
-+$(obj)/xengate-data.o: $(obj)/xengate.so
+ source "drivers/firmware/Kconfig"
+
+ source "fs/Kconfig.binfmt"
+@@ -465,6 +514,21 @@ config PCI_DOMAINS
+ bool
+ default PCI
+
++config XEN_PCIDEV_FRONTEND
++ bool "Xen PCI Frontend"
++ depends on PCI && XEN
++ default y
++ help
++ The PCI device frontend driver allows the kernel to import arbitrary
++ PCI devices from a PCI backend to support PCI driver domains.
++
++config XEN_PCIDEV_FE_DEBUG
++ bool "Xen PCI Frontend Debugging"
++ depends on XEN_PCIDEV_FRONTEND
++ default n
++ help
++ Enables some debug statements within the PCI Frontend.
++
+ source "drivers/pci/pcie/Kconfig"
+
+ source "drivers/pci/Kconfig"
+@@ -528,3 +592,16 @@ source "arch/ia64/Kconfig.debug"
+ source "security/Kconfig"
+
+ source "crypto/Kconfig"
+
+#
-+# .tmp_gate.o to calculate padding size for __kernel_syscall_via_epc
++# override default values of drivers/xen/Kconfig
+#
-+extra-$(CONFIG_XEN) += gate-skip.s .tmp_gate.o
++if XEN
++config XEN_SMPBOOT
++ default n
+
-+ifeq ($(CONFIG_XEN), y)
-+AFLAGS_gate.o += -D__KERNEL_SYSCALL_VIA_EPC_PADDING
-+$(obj)/gate.o: $(obj)/gate-skip.s FORCE
++config XEN_DEVMEM
++ default n
+endif
+
-+$(obj)/.tmp_gate.o: $(src)/gate.S FORCE
-+ $(call if_changed_dep,as_o_S)
-+
-+quiet_cmd_gate_size = GATE_SIZE $@
-+ cmd_gate_size = $(NM) --extern-only --print-size $(obj)/xengate.o | \
-+ $(AWK) '/__kernel_syscall_via_epc/{printf "\t.skip 0x"$$2" - "}' > $@; \
-+ $(NM) --extern-only --print-size $(obj)/.tmp_gate.o | \
-+ $(AWK) '/__kernel_syscall_via_epc/{printf "0x"$$2"\n"}' >> $@
-+
-+$(obj)/gate-skip.s: $(obj)/xengate.o $(obj)/.tmp_gate.o FORCE
-+ $(call if_changed,gate_size)
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/acpi.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/acpi.c
---- linux-2.6.18.8/arch/ia64/kernel/acpi.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/acpi.c 2008-02-15 16:21:49.000000000 -0800
++source "drivers/xen/Kconfig"
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/acpi.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/acpi.c
+--- linux-2.6.18.8/arch/ia64/kernel/acpi.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/acpi.c 2008-08-21 11:36:07.000000000 +0200
@@ -109,6 +109,10 @@ const char *acpi_get_sysname(void)
return "hpzx1";
} else if (!strcmp(hdr->oem_id, "SGI")) {
@@ -22798,9 +23093,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/acpi.c linux-2.6.18-xen-3.2.0/arch/ia
# else
# error Unknown platform. Fix acpi.c.
# endif
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/asm-offsets.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/asm-offsets.c
---- linux-2.6.18.8/arch/ia64/kernel/asm-offsets.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/asm-offsets.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/asm-offsets.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/asm-offsets.c
+--- linux-2.6.18.8/arch/ia64/kernel/asm-offsets.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/asm-offsets.c 2008-08-21 11:36:07.000000000 +0200
@@ -268,4 +268,29 @@ void foo(void)
DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64);
DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32);
@@ -22831,9 +23126,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/asm-offsets.c linux-2.6.18-xen-3.2.0/
+ DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat);
+#endif /* CONFIG_XEN */
}
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/crash.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/crash.c
---- linux-2.6.18.8/arch/ia64/kernel/crash.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/crash.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/crash.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/crash.c
+--- linux-2.6.18.8/arch/ia64/kernel/crash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/crash.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,222 @@
+/*
+ * arch/ia64/kernel/crash.c
@@ -23057,9 +23352,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/crash.c linux-2.6.18-xen-3.2.0/arch/i
+
+__initcall(machine_crash_setup);
+
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/crash_dump.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/crash_dump.c
---- linux-2.6.18.8/arch/ia64/kernel/crash_dump.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/crash_dump.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/crash_dump.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/crash_dump.c
+--- linux-2.6.18.8/arch/ia64/kernel/crash_dump.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/crash_dump.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,48 @@
+/*
+ * kernel/crash_dump.c - Memory preserving reboot related code.
@@ -23109,10 +23404,16 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/crash_dump.c linux-2.6.18-xen-3.2.0/a
+ return csize;
+}
+
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/efi.c
---- linux-2.6.18.8/arch/ia64/kernel/efi.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/efi.c 2008-02-15 16:21:49.000000000 -0800
-@@ -26,6 +26,7 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/efi.c
+--- linux-2.6.18.8/arch/ia64/kernel/efi.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/efi.c 2008-08-21 11:36:07.000000000 +0200
+@@ -21,11 +21,13 @@
+ * Skip non-WB memory and ignore empty memory ranges.
+ */
+ #include <linux/module.h>
++#include <linux/bootmem.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
#include <linux/types.h>
#include <linux/time.h>
#include <linux/efi.h>
@@ -23120,7 +23421,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
#include <asm/io.h>
#include <asm/kregs.h>
-@@ -34,6 +35,11 @@
+@@ -34,6 +36,11 @@
#include <asm/processor.h>
#include <asm/mca.h>
@@ -23132,7 +23433,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
#define EFI_DEBUG 0
extern efi_status_t efi_call_phys (void *, ...);
-@@ -41,7 +47,7 @@ extern efi_status_t efi_call_phys (void
+@@ -41,7 +48,7 @@ extern efi_status_t efi_call_phys (void
struct efi efi;
EXPORT_SYMBOL(efi);
static efi_runtime_services_t *runtime;
@@ -23141,7 +23442,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
#define efi_call_virt(f, args...) (*(f))(args)
-@@ -421,6 +427,8 @@ efi_init (void)
+@@ -421,6 +428,8 @@ efi_init (void)
mem_limit = memparse(cp + 4, &cp);
} else if (memcmp(cp, "max_addr=", 9) == 0) {
max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp));
@@ -23150,7 +23451,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
} else {
while (*cp != ' ' && *cp)
++cp;
-@@ -428,6 +436,8 @@ efi_init (void)
+@@ -428,6 +437,8 @@ efi_init (void)
++cp;
}
}
@@ -23159,7 +23460,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
if (max_addr != ~0UL)
printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20);
-@@ -894,7 +904,8 @@ find_memmap_space (void)
+@@ -894,7 +905,8 @@ find_memmap_space (void)
as = max(contig_low, md->phys_addr);
ae = min(contig_high, efi_md_end(md));
@@ -23169,7 +23470,19 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
ae = min(ae, max_addr);
if (ae <= as)
continue;
-@@ -1004,7 +1015,8 @@ efi_memmap_init(unsigned long *s, unsign
+@@ -965,6 +977,11 @@ efi_memmap_init(unsigned long *s, unsign
+ if (!is_available_memory(md))
+ continue;
+
++#ifdef CONFIG_CRASH_DUMP
++ /* saved_max_pfn should ignore max_addr= command line arg */
++ if (saved_max_pfn < (efi_md_end(md) >> PAGE_SHIFT))
++ saved_max_pfn = (efi_md_end(md) >> PAGE_SHIFT);
++#endif
+ /*
+ * Round ends inward to granule boundaries
+ * Give trimmings to uncached allocator
+@@ -1004,7 +1021,8 @@ efi_memmap_init(unsigned long *s, unsign
} else
ae = efi_md_end(md);
@@ -23179,7 +23492,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
ae = min(ae, max_addr);
if (ae <= as)
continue;
-@@ -1033,21 +1045,22 @@ efi_memmap_init(unsigned long *s, unsign
+@@ -1033,21 +1051,22 @@ efi_memmap_init(unsigned long *s, unsign
*e = (u64)++k;
}
@@ -23211,7 +23524,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
res = NULL;
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
-@@ -1106,7 +1119,7 @@ efi_initialize_iomem_resources(struct re
+@@ -1106,7 +1125,7 @@ efi_initialize_iomem_resources(struct re
res->end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
res->flags = flags;
@@ -23220,7 +23533,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
kfree(res);
else {
/*
-@@ -1114,8 +1127,135 @@ efi_initialize_iomem_resources(struct re
+@@ -1114,8 +1133,135 @@ efi_initialize_iomem_resources(struct re
* kernel data so we try it repeatedly and
* let the resource manager test it.
*/
@@ -23248,7 +23561,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
}
+
+#ifdef CONFIG_PROC_IOMEM_MACHINE
-+static int
++static void
+efi_initialize_iomem_machine_resources(void)
+{
+ unsigned long size;
@@ -23262,7 +23575,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
+ for (size = 1024; 1; size += 1024) {
+ memmap_info = kmalloc(size, GFP_KERNEL);
+ if (memmap_info == NULL)
-+ return -ENOMEM;
++ return; /* -ENOMEM, but no way to return error */
+
+ memmap.nr_entries = size;
+ set_xen_guest_handle(memmap.buffer, memmap_info);
@@ -23358,9 +23671,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/efi.c linux-2.6.18-xen-3.2.0/arch/ia6
+ return ~0UL;
+}
+#endif
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/entry.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/entry.S
---- linux-2.6.18.8/arch/ia64/kernel/entry.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/entry.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/entry.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/entry.S
+--- linux-2.6.18.8/arch/ia64/kernel/entry.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/entry.S 2008-08-21 11:36:07.000000000 +0200
@@ -180,7 +180,7 @@ END(sys_clone)
* called. The code starting at .map relies on this. The rest of the code
* doesn't care about the interrupt masking status.
@@ -23507,9 +23820,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/entry.S linux-2.6.18-xen-3.2.0/arch/i
data8 sys_ni_syscall // reserved for vserver
data8 sys_waitid // 1270
data8 sys_add_key
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/fsys.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/fsys.S
---- linux-2.6.18.8/arch/ia64/kernel/fsys.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/fsys.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/fsys.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/fsys.S
+--- linux-2.6.18.8/arch/ia64/kernel/fsys.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/fsys.S 2008-08-21 11:36:07.000000000 +0200
@@ -516,11 +516,34 @@ ENTRY(fsys_fallback_syscall)
adds r17=-1024,r15
movl r14=sys_call_table
@@ -23571,9 +23884,37 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/fsys.S linux-2.6.18-xen-3.2.0/arch/ia
cmp.eq p8,p0=r3,r0 // A
(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/gate.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/gate.S
---- linux-2.6.18.8/arch/ia64/kernel/gate.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/gate.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/gate.lds.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/gate.lds.S
+--- linux-2.6.18.8/arch/ia64/kernel/gate.lds.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/gate.lds.S 2008-08-21 11:36:07.000000000 +0200
+@@ -28,6 +28,24 @@ SECTIONS
+ . = GATE_ADDR + 0x500;
+
+ .data.patch : {
++#ifdef __XEN_IA64_VDSO_PARAVIRT
++#define __start_gate_mckinley_e9_patchlist \
++ __start_gate_mckinley_e9_patchlist_xen
++#define __end_gate_mckinley_e9_patchlist \
++ __end_gate_mckinley_e9_patchlist_xen
++#define __start_gate_vtop_patchlist \
++ __start_gate_vtop_patchlist_xen
++#define __end_gate_vtop_patchlist \
++ __end_gate_vtop_patchlist_xen
++#define __start_gate_fsyscall_patchlist \
++ __start_gate_fsyscall_patchlist_xen
++#define __end_gate_fsyscall_patchlist \
++ __end_gate_fsyscall_patchlist_xen
++#define __start_gate_brl_fsys_bubble_down_patchlist \
++ __start_gate_brl_fsys_bubble_down_patchlist_xen
++#define __end_gate_brl_fsys_bubble_down_patchlist \
++ __end_gate_brl_fsys_bubble_down_patchlist_xen
++#endif
+ __start_gate_mckinley_e9_patchlist = .;
+ *(.data.patch.mckinley_e9)
+ __end_gate_mckinley_e9_patchlist = .;
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/gate.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/gate.S
+--- linux-2.6.18.8/arch/ia64/kernel/gate.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/gate.S 2008-08-21 11:36:07.000000000 +0200
@@ -32,102 +32,6 @@
[1:](pr)brl.cond.sptk 0; \
.xdata4 ".data.patch.brl_fsys_bubble_down", 1b-.
@@ -23832,37 +24173,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/gate.S linux-2.6.18-xen-3.2.0/arch/ia
+.include "arch/ia64/kernel/gate-skip.s"
+#endif
+END(__kernel_syscall_via_epc)
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/gate.lds.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/gate.lds.S
---- linux-2.6.18.8/arch/ia64/kernel/gate.lds.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/gate.lds.S 2008-02-15 16:21:49.000000000 -0800
-@@ -28,6 +28,24 @@ SECTIONS
- . = GATE_ADDR + 0x500;
-
- .data.patch : {
-+#ifdef __XEN_IA64_VDSO_PARAVIRT
-+#define __start_gate_mckinley_e9_patchlist \
-+ __start_gate_mckinley_e9_patchlist_xen
-+#define __end_gate_mckinley_e9_patchlist \
-+ __end_gate_mckinley_e9_patchlist_xen
-+#define __start_gate_vtop_patchlist \
-+ __start_gate_vtop_patchlist_xen
-+#define __end_gate_vtop_patchlist \
-+ __end_gate_vtop_patchlist_xen
-+#define __start_gate_fsyscall_patchlist \
-+ __start_gate_fsyscall_patchlist_xen
-+#define __end_gate_fsyscall_patchlist \
-+ __end_gate_fsyscall_patchlist_xen
-+#define __start_gate_brl_fsys_bubble_down_patchlist \
-+ __start_gate_brl_fsys_bubble_down_patchlist_xen
-+#define __end_gate_brl_fsys_bubble_down_patchlist \
-+ __end_gate_brl_fsys_bubble_down_patchlist_xen
-+#endif
- __start_gate_mckinley_e9_patchlist = .;
- *(.data.patch.mckinley_e9)
- __end_gate_mckinley_e9_patchlist = .;
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/head.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/head.S
---- linux-2.6.18.8/arch/ia64/kernel/head.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/head.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/head.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/head.S
+--- linux-2.6.18.8/arch/ia64/kernel/head.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/head.S 2008-08-21 11:36:07.000000000 +0200
@@ -367,6 +367,12 @@ start_ap:
;;
(isBP) st8 [r2]=r28 // save the address of the boot param area passed by the bootloader
@@ -23876,9 +24189,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/head.S linux-2.6.18-xen-3.2.0/arch/ia
#ifdef CONFIG_SMP
(isAP) br.call.sptk.many rp=start_secondary
.ret0:
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/iosapic.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/iosapic.c
---- linux-2.6.18.8/arch/ia64/kernel/iosapic.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/iosapic.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/iosapic.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/iosapic.c
+--- linux-2.6.18.8/arch/ia64/kernel/iosapic.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/iosapic.c 2008-08-21 11:36:07.000000000 +0200
@@ -159,6 +159,75 @@ static unsigned char pcat_compat __devin
static int iosapic_kmalloc_ok;
static LIST_HEAD(free_rte_list);
@@ -24003,9 +24316,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/iosapic.c linux-2.6.18-xen-3.2.0/arch
if (pcat_compat) {
/*
* Disable the compatibility mode interrupts (8259 style),
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/irq_ia64.c
---- linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/irq_ia64.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/irq_ia64.c
+--- linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/irq_ia64.c 2008-08-21 11:36:07.000000000 +0200
@@ -30,6 +30,9 @@
#include <linux/smp_lock.h>
#include <linux/threads.h>
@@ -24044,7 +24357,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c linux-2.6.18-xen-3.2.0/arc
pos = vector - IA64_FIRST_DEVICE_VECTOR;
if (!test_and_clear_bit(pos, ia64_vector_mask))
printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
-@@ -240,12 +257,340 @@ static struct irqaction ipi_irqaction =
+@@ -240,12 +257,342 @@ static struct irqaction ipi_irqaction =
};
#endif
@@ -24325,12 +24638,11 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c linux-2.6.18-xen-3.2.0/arc
+xen_platform_send_ipi(int cpu, int vector, int delivery_mode, int redirect)
+{
+ int irq = -1;
++ extern void xen_send_ipi(int cpu, int vec);
+
+#ifdef CONFIG_SMP
+ /* TODO: we need to call vcpu_up here */
+ if (unlikely(vector == ap_wakeup_vector)) {
-+ extern void xen_send_ipi (int cpu, int vec);
-+
+ /* XXX
+ * This should be in __cpu_up(cpu) in ia64 smpboot.c
+ * like x86. But don't want to modify it,
@@ -24357,6 +24669,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c linux-2.6.18-xen-3.2.0/arc
+ case IA64_CPEP_VECTOR:
+ irq = per_cpu(ipi_to_irq, cpu)[CPEP_VECTOR];
+ break;
++ case IA64_TIMER_VECTOR:
++ xen_send_ipi(cpu, vector);
++ return;
+ default:
+ printk(KERN_WARNING "Unsupported IPI type 0x%x\n",
+ vector);
@@ -24385,7 +24700,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c linux-2.6.18-xen-3.2.0/arc
for (irq = 0; irq < NR_IRQS; ++irq)
if (irq_to_vector(irq) == vec) {
desc = irq_desc + irq;
-@@ -267,6 +612,10 @@ init_IRQ (void)
+@@ -267,6 +614,10 @@ init_IRQ (void)
pfm_init_percpu();
#endif
platform_irq_init();
@@ -24396,7 +24711,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c linux-2.6.18-xen-3.2.0/arc
}
void
-@@ -276,6 +625,13 @@ ia64_send_ipi (int cpu, int vector, int
+@@ -276,6 +627,13 @@ ia64_send_ipi (int cpu, int vector, int
unsigned long ipi_data;
unsigned long phys_cpu_id;
@@ -24410,10 +24725,10 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/irq_ia64.c linux-2.6.18-xen-3.2.0/arc
#ifdef CONFIG_SMP
phys_cpu_id = cpu_physical_id(cpu);
#else
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/machine_kexec.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/machine_kexec.c
---- linux-2.6.18.8/arch/ia64/kernel/machine_kexec.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/machine_kexec.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,145 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/machine_kexec.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/machine_kexec.c
+--- linux-2.6.18.8/arch/ia64/kernel/machine_kexec.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/machine_kexec.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,204 @@
+/*
+ * arch/ia64/kernel/machine_kexec.c
+ *
@@ -24558,10 +24873,143 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/machine_kexec.c linux-2.6.18-xen-3.2.
+ xki->reboot_code_buffer =
+ kexec_page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+}
++
++static struct resource xen_hypervisor_heap_res;
++
++int __init machine_kexec_setup_resources(struct resource *hypervisor,
++ struct resource *phys_cpus,
++ int nr_phys_cpus)
++{
++ xen_kexec_range_t range;
++ int k;
++
++ /* fill in xen_hypervisor_heap_res with hypervisor heap
++ * machine address range
++ */
++
++ memset(&range, 0, sizeof(range));
++ range.range = KEXEC_RANGE_MA_XENHEAP;
++
++ if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
++ return -1;
++
++ xen_hypervisor_heap_res.name = "Hypervisor heap";
++ xen_hypervisor_heap_res.start = range.start;
++ xen_hypervisor_heap_res.end = range.start + range.size - 1;
++ xen_hypervisor_heap_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
++
++ /* The per-cpu crash note resources belong inside the
++ * hypervisor heap resource */
++ for (k = 0; k < nr_phys_cpus; k++)
++ request_resource(&xen_hypervisor_heap_res, phys_cpus + k);
++
++ /* fill in efi_memmap_res with EFI memmap machine address range */
++
++ memset(&range, 0, sizeof(range));
++ range.range = KEXEC_RANGE_MA_EFI_MEMMAP;
++
++ if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
++ return -1;
++
++ efi_memmap_res.start = range.start;
++ efi_memmap_res.end = range.start + range.size - 1;
++
++ /* fill in boot_param_res with boot parameter machine address range */
++
++ memset(&range, 0, sizeof(range));
++ range.range = KEXEC_RANGE_MA_BOOT_PARAM;
++
++ if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
++ return -1;
++
++ boot_param_res.start = range.start;
++ boot_param_res.end = range.start + range.size - 1;
++
++ return 0;
++}
++
++void machine_kexec_register_resources(struct resource *res)
++{
++ request_resource(res, &xen_hypervisor_heap_res);
++}
+#endif /* CONFIG_XEN */
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/mca.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/mca.c
---- linux-2.6.18.8/arch/ia64/kernel/mca.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/mca.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/Makefile linux-2.6.18-xen-3.3.0/arch/ia64/kernel/Makefile
+--- linux-2.6.18.8/arch/ia64/kernel/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -28,6 +28,8 @@ obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
+ obj-$(CONFIG_CPU_FREQ) += cpufreq/
+ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
+ obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
++obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
++obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+ obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
+ obj-$(CONFIG_AUDIT) += audit.o
+ mca_recovery-y += mca_drv.o mca_drv_asm.o
+@@ -61,3 +63,61 @@ $(obj)/gate-syms.o: $(obj)/gate.lds $(ob
+ # We must build gate.so before we can assemble it.
+ # Note: kbuild does not track this dependency due to usage of .incbin
+ $(obj)/gate-data.o: $(obj)/gate.so
++
++#
++# gate page paravirtualization for xen
++#
++obj-$(CONFIG_XEN) += xengate-data.o
++
++ifeq ($(CONFIG_XEN), y)
++# The gate DSO image is built using a special linker script.
++targets += xengate.so xengate-syms.o
++endif
++
++extra-$(CONFIG_XEN) += xengate.so xengate.lds xengate.o
++
++AFLAGS_xengate.o += -D__XEN_IA64_VDSO_PARAVIRT
++$(obj)/xengate.o: $(src)/gate.S FORCE
++ $(call if_changed_dep,as_o_S)
++
++CPPFLAGS_xengate.lds := -P -C -U$(ARCH) -D__XEN_IA64_VDSO_PARAVIRT
++$(obj)/xengate.lds: $(src)/gate.lds.S
++ $(call if_changed_dep,cpp_lds_S)
++
++GATECFLAGS_xengate.so = -shared -s -Wl,-soname=linux-gate.so.1 \
++ $(call ld-option, -Wl$(comma)--hash-style=sysv)
++$(obj)/xengate.so: $(obj)/xengate.lds $(obj)/xengate.o FORCE
++ $(call if_changed,gate)
++
++ifeq ($(CONFIG_XEN), y)
++$(obj)/built-in.o: $(obj)/xengate-syms.o
++$(obj)/built-in.o: ld_flags += -R $(obj)/xengate-syms.o
++$(obj)/mca_recovery.o: $(obj)/gate-syms.o $(obj)/xengate-syms.o
++endif
++
++GATECFLAGS_xengate-syms.o = -r
++$(obj)/xengate-syms.o: $(obj)/xengate.lds $(obj)/xengate.o FORCE
++ $(call if_changed,gate)
++$(obj)/xengate-data.o: $(obj)/xengate.so
++
++#
++# .tmp_gate.o to calculate padding size for __kernel_syscall_via_epc
++#
++extra-$(CONFIG_XEN) += gate-skip.s .tmp_gate.o
++
++ifeq ($(CONFIG_XEN), y)
++AFLAGS_gate.o += -D__KERNEL_SYSCALL_VIA_EPC_PADDING
++$(obj)/gate.o: $(obj)/gate-skip.s FORCE
++endif
++
++$(obj)/.tmp_gate.o: $(src)/gate.S FORCE
++ $(call if_changed_dep,as_o_S)
++
++quiet_cmd_gate_size = GATE_SIZE $@
++ cmd_gate_size = $(NM) --extern-only --print-size $(obj)/xengate.o | \
++ $(AWK) '/__kernel_syscall_via_epc/{printf "\t.skip 0x"$$2" - "}' > $@; \
++ $(NM) --extern-only --print-size $(obj)/.tmp_gate.o | \
++ $(AWK) '/__kernel_syscall_via_epc/{printf "0x"$$2"\n"}' >> $@
++
++$(obj)/gate-skip.s: $(obj)/xengate.o $(obj)/.tmp_gate.o FORCE
++ $(call if_changed,gate_size)
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/mca.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/mca.c
+--- linux-2.6.18.8/arch/ia64/kernel/mca.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/mca.c 2008-08-21 11:36:07.000000000 +0200
@@ -79,6 +79,7 @@
#include <asm/system.h>
#include <asm/sal.h>
@@ -24618,9 +25066,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/mca.c linux-2.6.18-xen-3.2.0/arch/ia6
if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/pal.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/pal.S
---- linux-2.6.18.8/arch/ia64/kernel/pal.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/pal.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/pal.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/pal.S
+--- linux-2.6.18.8/arch/ia64/kernel/pal.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/pal.S 2008-08-21 11:36:07.000000000 +0200
@@ -16,6 +16,7 @@
#include <asm/processor.h>
@@ -24647,9 +25095,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/pal.S linux-2.6.18-xen-3.2.0/arch/ia6
/*
* Make a PAL call using the stacked registers calling convention.
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/patch.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/patch.c
---- linux-2.6.18.8/arch/ia64/kernel/patch.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/patch.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/patch.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/patch.c
+--- linux-2.6.18.8/arch/ia64/kernel/patch.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/patch.c 2008-08-21 11:36:07.000000000 +0200
@@ -184,9 +184,37 @@ patch_brl_fsys_bubble_down (unsigned lon
ia64_srlz_i();
}
@@ -24688,9 +25136,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/patch.c linux-2.6.18-xen-3.2.0/arch/i
# define START(name) ((unsigned long) __start_gate_##name##_patchlist)
# define END(name) ((unsigned long)__end_gate_##name##_patchlist)
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/perfmon.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/perfmon.c
---- linux-2.6.18.8/arch/ia64/kernel/perfmon.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/perfmon.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/perfmon.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/perfmon.c
+--- linux-2.6.18.8/arch/ia64/kernel/perfmon.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/perfmon.c 2008-08-21 11:36:07.000000000 +0200
@@ -52,6 +52,31 @@
#include <asm/delay.h>
@@ -24888,10 +25336,10 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/perfmon.c linux-2.6.18-xen-3.2.0/arch
DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task->pid : -1));
prev_state = ctx->ctx_state;
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/relocate_kernel.S
---- linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/relocate_kernel.S 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,380 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/relocate_kernel.S
+--- linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/relocate_kernel.S 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,338 @@
+/*
+ * arch/ia64/kernel/relocate_kernel.S
+ *
@@ -24914,11 +25362,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+ */
+GLOBAL_ENTRY(relocate_new_kernel)
+ .prologue
-+#ifdef CONFIG_XEN
-+ alloc r31=ar.pfs,8,0,0,0
-+#else
+ alloc r31=ar.pfs,4,0,0,0
-+#endif
+ .body
+.reloc_entry:
+{
@@ -24931,11 +25375,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+ srlz.i
+}
+ ;;
-+#ifdef CONFIG_XEN
-+ dep r2=0,r2,60,4 //to physical address
-+#else
+ dep r2=0,r2,61,3 //to physical address
-+#endif
+ ;;
+ //first switch to physical mode
+ add r3=1f-.reloc_entry, r2
@@ -24960,18 +25400,13 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+ //physical mode code begin
+ mov b6=in1
+#ifdef CONFIG_XEN
-+ dep r28=0,in2,60,4 //to physical address
++ mov r28=in2 //already a physical address
+#else
+ dep r28=0,in2,61,3 //to physical address
-+#endif
+
+ // purge all TC entries
+#define O(member) IA64_CPUINFO_##member##_OFFSET
-+#ifdef CONFIG_XEN
-+ mov r2=in4 // load phys addr of cpu_info into r2
-+#else
+ GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2
-+#endif
+ ;;
+ addl r17=O(PTCE_STRIDE),r2
+ addl r2=O(PTCE_BASE),r2
@@ -25005,11 +25440,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+ srlz.i
+ ;;
+ //purge TR entry for kernel text and data
-+#ifdef CONFIG_XEN
-+ mov r16=in5
-+#else
+ movl r16=KERNEL_START
-+#endif
+ mov r18=KERNEL_TR_PAGE_SHIFT<<2
+ ;;
+ ptr.i r16, r18
@@ -25040,11 +25471,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+ mov r16=IA64_KR(CURRENT_STACK)
+ ;;
+ shl r16=r16,IA64_GRANULE_SHIFT
-+#ifdef CONFIG_XEN
-+ mov r19=in6
-+#else
+ movl r19=PAGE_OFFSET
-+#endif
+ ;;
+ add r16=r19,r16
+ mov r18=IA64_GRANULE_SHIFT<<2
@@ -25053,20 +25480,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+ ;;
+ srlz.i
+ ;;
-+
-+#ifdef XEN
-+ /* XXX: Is this neccessary ??? */
-+ // purge TR entry for VHPT
-+ mov r16=in7
-+ ;;
-+ dep r16=0,r16,0,IA64_GRANULE_SHIFT
-+ mov r18=IA64_GRANULE_SHIFT<<2
-+ ;;
-+ ptr.d r16,r18
-+ ;;
-+ srlz.i
-+ ;;
-+#endif
++#endif /* ! CONFIG_XEN */
+
+ //copy segments
+ movl r16=PAGE_MASK
@@ -25115,18 +25529,10 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+
+.align 32
+memory_stack:
-+#ifdef CONFIG_XEN
-+ .fill 4096, 1, 0
-+#else
+ .fill 8192, 1, 0
-+#endif
+memory_stack_end:
+register_stack:
-+#ifdef CONFIG_XEN
-+ .fill 4096, 1, 0
-+#else
+ .fill 8192, 1, 0
-+#endif
+register_stack_end:
+relocate_new_kernel_end:
+END(relocate_new_kernel)
@@ -25272,9 +25678,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/relocate_kernel.S linux-2.6.18-xen-3.
+END(ia64_dump_cpu_regs)
+
+
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/salinfo.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/salinfo.c
---- linux-2.6.18.8/arch/ia64/kernel/salinfo.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/salinfo.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/salinfo.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/salinfo.c
+--- linux-2.6.18.8/arch/ia64/kernel/salinfo.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/salinfo.c 2008-08-21 11:36:07.000000000 +0200
@@ -375,6 +375,25 @@ salinfo_log_open(struct inode *inode, st
data->open = 0;
return -ENOMEM;
@@ -25332,9 +25738,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/salinfo.c linux-2.6.18-xen-3.2.0/arch
vfree(data->log_buffer);
vfree(data->oemdata);
data->log_buffer = NULL;
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/setup.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/setup.c
---- linux-2.6.18.8/arch/ia64/kernel/setup.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/setup.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/setup.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/setup.c
+--- linux-2.6.18.8/arch/ia64/kernel/setup.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/setup.c 2008-08-21 11:36:07.000000000 +0200
@@ -43,6 +43,8 @@
#include <linux/initrd.h>
#include <linux/pm.h>
@@ -25450,15 +25856,15 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/setup.c linux-2.6.18-xen-3.2.0/arch/i
+ }
+ }
+ }
-+#ifdef CONFIG_XEN
-+ }
-+#endif
+ efi_memmap_res.start = ia64_boot_param->efi_memmap;
+ efi_memmap_res.end = efi_memmap_res.start +
+ ia64_boot_param->efi_memmap_size;
+ boot_param_res.start = kexec_virt_to_phys(ia64_boot_param);
+ boot_param_res.end = boot_param_res.start +
+ sizeof(*ia64_boot_param);
++#ifdef CONFIG_XEN
++ }
++#endif
+ }
+#endif
/* end of memory marker */
@@ -25623,9 +26029,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/setup.c linux-2.6.18-xen-3.2.0/arch/i
pm_idle = default_idle;
}
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/smp.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/smp.c
---- linux-2.6.18.8/arch/ia64/kernel/smp.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/smp.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/smp.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/smp.c
+--- linux-2.6.18.8/arch/ia64/kernel/smp.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/smp.c 2008-08-21 11:36:07.000000000 +0200
@@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/efi.h>
@@ -25708,9 +26114,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/smp.c linux-2.6.18-xen-3.2.0/arch/ia6
call_data = &data;
mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC */
send_IPI_allbutself(IPI_CALL_FUNC);
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/time.c linux-2.6.18-xen-3.2.0/arch/ia64/kernel/time.c
---- linux-2.6.18.8/arch/ia64/kernel/time.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/time.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/time.c linux-2.6.18-xen-3.3.0/arch/ia64/kernel/time.c
+--- linux-2.6.18.8/arch/ia64/kernel/time.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/time.c 2008-08-21 11:36:07.000000000 +0200
@@ -29,6 +29,14 @@
#include <asm/sections.h>
#include <asm/system.h>
@@ -25958,9 +26364,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/time.c linux-2.6.18-xen-3.2.0/arch/ia
/* Setup the CPU local timer tick */
ia64_cpu_local_tick();
}
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/vmlinux.lds.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/vmlinux.lds.S
---- linux-2.6.18.8/arch/ia64/kernel/vmlinux.lds.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/vmlinux.lds.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/vmlinux.lds.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/vmlinux.lds.S
+--- linux-2.6.18.8/arch/ia64/kernel/vmlinux.lds.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/vmlinux.lds.S 2008-08-21 11:36:07.000000000 +0200
@@ -183,6 +183,12 @@ SECTIONS
__start_gate_section = .;
*(.data.gate)
@@ -25974,27 +26380,64 @@ diff -rpuN linux-2.6.18.8/arch/ia64/kernel/vmlinux.lds.S linux-2.6.18-xen-3.2.0/
}
. = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose kernel data */
-diff -rpuN linux-2.6.18.8/arch/ia64/kernel/xengate-data.S linux-2.6.18-xen-3.2.0/arch/ia64/kernel/xengate-data.S
---- linux-2.6.18.8/arch/ia64/kernel/xengate-data.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/kernel/xengate-data.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/kernel/xengate-data.S linux-2.6.18-xen-3.3.0/arch/ia64/kernel/xengate-data.S
+--- linux-2.6.18.8/arch/ia64/kernel/xengate-data.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/kernel/xengate-data.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,3 @@
+ .section .data.gate.xen, "aw"
+
+ .incbin "arch/ia64/kernel/xengate.so"
-diff -rpuN linux-2.6.18.8/arch/ia64/mm/contig.c linux-2.6.18-xen-3.2.0/arch/ia64/mm/contig.c
---- linux-2.6.18.8/arch/ia64/mm/contig.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/mm/contig.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/Makefile linux-2.6.18-xen-3.3.0/arch/ia64/Makefile
+--- linux-2.6.18.8/arch/ia64/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -45,6 +45,12 @@ ifeq ($(call cc-version),0304)
+ endif
+
+ CFLAGS += $(cflags-y)
++
++cppflags-$(CONFIG_XEN) += \
++ -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION)
++
++CPPFLAGS += $(cppflags-y)
++
+ head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
+
+ libs-y += arch/ia64/lib/
+@@ -54,7 +60,9 @@ core-$(CONFIG_IA64_DIG) += arch/ia64/di
+ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
+ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
+ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
++core-$(CONFIG_IA64_XEN) += arch/ia64/dig/
+ core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/
++core-$(CONFIG_XEN) += arch/ia64/xen/
+
+ drivers-$(CONFIG_PCI) += arch/ia64/pci/
+ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
+@@ -87,8 +95,8 @@ CLEAN_FILES += vmlinux.gz bootloader
+ boot: lib/lib.a vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $@
+
+-install: vmlinux.gz
+- sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
++install:
++ -yes | sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
+
+ define archhelp
+ echo '* compressed - Build compressed kernel image'
+diff -rpuN linux-2.6.18.8/arch/ia64/mm/contig.c linux-2.6.18-xen-3.3.0/arch/ia64/mm/contig.c
+--- linux-2.6.18.8/arch/ia64/mm/contig.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/mm/contig.c 2008-08-21 11:36:07.000000000 +0200
@@ -18,6 +18,9 @@
#include <linux/efi.h>
#include <linux/mm.h>
#include <linux/swap.h>
-+#ifdef CONFIG_XEN
++#if defined(CONFIG_XEN) && defined(CONFIG_KEXEC)
+#include <linux/kexec.h>
+#endif
#include <asm/meminit.h>
#include <asm/pgalloc.h>
-@@ -172,8 +175,17 @@ find_memory (void)
+@@ -172,8 +175,12 @@ find_memory (void)
/* Free all available memory, then mark bootmem-map as being in use. */
efi_memmap_walk(filter_rsvd_memory, free_bootmem);
reserve_bootmem(bootmap_start, bootmap_size);
@@ -26004,17 +26447,35 @@ diff -rpuN linux-2.6.18.8/arch/ia64/mm/contig.c linux-2.6.18-xen-3.2.0/arch/ia64
find_initrd();
+
-+#ifdef CONFIG_CRASH_DUMP
-+ /* If we are doing a crash dump, we still need to know the real mem
-+ * size before original memory map is * reset. */
-+ saved_max_pfn = max_pfn;
-+#endif
}
#ifdef CONFIG_SMP
-diff -rpuN linux-2.6.18.8/arch/ia64/mm/init.c linux-2.6.18-xen-3.2.0/arch/ia64/mm/init.c
---- linux-2.6.18.8/arch/ia64/mm/init.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/mm/init.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/mm/discontig.c linux-2.6.18-xen-3.3.0/arch/ia64/mm/discontig.c
+--- linux-2.6.18.8/arch/ia64/mm/discontig.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/mm/discontig.c 2008-08-21 11:36:07.000000000 +0200
+@@ -21,6 +21,9 @@
+ #include <linux/acpi.h>
+ #include <linux/efi.h>
+ #include <linux/nodemask.h>
++#if defined(CONFIG_XEN) && defined(CONFIG_KEXEC)
++#include <linux/kexec.h>
++#endif
+ #include <asm/pgalloc.h>
+ #include <asm/tlb.h>
+ #include <asm/meminit.h>
+@@ -502,6 +505,9 @@ void __init find_memory(void)
+ reserve_pernode_space();
+ memory_less_nodes();
+ initialize_pernode_data();
++#if defined(CONFIG_XEN) && defined(CONFIG_KEXEC)
++ xen_machine_kexec_setup_resources();
++#endif
+
+ max_pfn = max_low_pfn;
+
+diff -rpuN linux-2.6.18.8/arch/ia64/mm/init.c linux-2.6.18-xen-3.3.0/arch/ia64/mm/init.c
+--- linux-2.6.18.8/arch/ia64/mm/init.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/mm/init.c 2008-08-21 11:36:07.000000000 +0200
@@ -303,16 +303,34 @@ static void __init
setup_gate (void)
{
@@ -26052,9 +26513,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/mm/init.c linux-2.6.18-xen-3.2.0/arch/ia64/m
put_kernel_page(page, GATE_ADDR + PAGE_SIZE, PAGE_GATE);
#else
put_kernel_page(page, GATE_ADDR + PERCPU_PAGE_SIZE, PAGE_GATE);
-diff -rpuN linux-2.6.18.8/arch/ia64/mm/ioremap.c linux-2.6.18-xen-3.2.0/arch/ia64/mm/ioremap.c
---- linux-2.6.18.8/arch/ia64/mm/ioremap.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/mm/ioremap.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/mm/ioremap.c linux-2.6.18-xen-3.3.0/arch/ia64/mm/ioremap.c
+--- linux-2.6.18.8/arch/ia64/mm/ioremap.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/mm/ioremap.c 2008-08-21 11:36:07.000000000 +0200
@@ -16,6 +16,9 @@
static inline void __iomem *
__ioremap (unsigned long offset, unsigned long size)
@@ -26065,20 +26526,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/mm/ioremap.c linux-2.6.18-xen-3.2.0/arch/ia6
return (void __iomem *) (__IA64_UNCACHED_OFFSET | offset);
}
-diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/Makefile linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/Makefile
---- linux-2.6.18.8/arch/ia64/oprofile/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -8,3 +8,7 @@ DRIVER_OBJS := $(addprefix ../../../driv
-
- oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
- oprofile-$(CONFIG_PERFMON) += perfmon.o
-+ifeq ($(CONFIG_XEN), y)
-+oprofile-$(CONFIG_PERFMON) += xenoprof.o \
-+ ../../../drivers/xen/xenoprof/xenoprofile.o
-+endif
-diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/init.c linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/init.c
---- linux-2.6.18.8/arch/ia64/oprofile/init.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/init.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/init.c linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/init.c
+--- linux-2.6.18.8/arch/ia64/oprofile/init.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/init.c 2008-08-21 11:36:07.000000000 +0200
@@ -11,6 +11,8 @@
#include <linux/oprofile.h>
#include <linux/init.h>
@@ -26115,9 +26565,20 @@ diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/init.c linux-2.6.18-xen-3.2.0/arch/
#ifdef CONFIG_PERFMON
perfmon_exit();
#endif
-diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/oprofile_perfmon.h linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/oprofile_perfmon.h
---- linux-2.6.18.8/arch/ia64/oprofile/oprofile_perfmon.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/oprofile_perfmon.h 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/Makefile linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/Makefile
+--- linux-2.6.18.8/arch/ia64/oprofile/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -8,3 +8,7 @@ DRIVER_OBJS := $(addprefix ../../../driv
+
+ oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
+ oprofile-$(CONFIG_PERFMON) += perfmon.o
++ifeq ($(CONFIG_XEN), y)
++oprofile-$(CONFIG_PERFMON) += xenoprof.o \
++ ../../../drivers/xen/xenoprof/xenoprofile.o
++endif
+diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/oprofile_perfmon.h linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/oprofile_perfmon.h
+--- linux-2.6.18.8/arch/ia64/oprofile/oprofile_perfmon.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/oprofile_perfmon.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,30 @@
+#ifndef OPROFILE_PERFMON_H
+#define OPROFILE_PERFMON_H
@@ -26149,9 +26610,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/oprofile_perfmon.h linux-2.6.18-xen
+#endif /* CONFIG_XEN */
+
+#endif /* OPROFILE_PERFMON_H */
-diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/perfmon.c linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/perfmon.c
---- linux-2.6.18.8/arch/ia64/oprofile/perfmon.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/perfmon.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/perfmon.c linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/perfmon.c
+--- linux-2.6.18.8/arch/ia64/oprofile/perfmon.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/perfmon.c 2008-08-21 11:36:07.000000000 +0200
@@ -13,6 +13,7 @@
#include <asm/perfmon.h>
#include <asm/ptrace.h>
@@ -26227,9 +26688,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/perfmon.c linux-2.6.18-xen-3.2.0/ar
- pfm_unregister_buffer_fmt(oprofile_fmt.fmt_uuid);
+ __perfmon_exit();
}
-diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/xenoprof.c linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/xenoprof.c
---- linux-2.6.18.8/arch/ia64/oprofile/xenoprof.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/oprofile/xenoprof.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/xenoprof.c linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/xenoprof.c
+--- linux-2.6.18.8/arch/ia64/oprofile/xenoprof.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/oprofile/xenoprof.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,142 @@
+/******************************************************************************
+ * xenoprof ia64 specific part
@@ -26373,9 +26834,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/oprofile/xenoprof.c linux-2.6.18-xen-3.2.0/a
+
+ return ret;
+}
-diff -rpuN linux-2.6.18.8/arch/ia64/pci/pci.c linux-2.6.18-xen-3.2.0/arch/ia64/pci/pci.c
---- linux-2.6.18.8/arch/ia64/pci/pci.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/pci/pci.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/pci/pci.c linux-2.6.18-xen-3.3.0/arch/ia64/pci/pci.c
+--- linux-2.6.18.8/arch/ia64/pci/pci.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/pci/pci.c 2008-08-21 11:36:07.000000000 +0200
@@ -30,6 +30,15 @@
#include <asm/irq.h>
#include <asm/hw_irq.h>
@@ -26625,9 +27086,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/pci/pci.c linux-2.6.18-xen-3.2.0/arch/ia64/p
+}
+EXPORT_SYMBOL(xen_pcibios_setup_root_windows);
+#endif
-diff -rpuN linux-2.6.18.8/arch/ia64/sn/kernel/setup.c linux-2.6.18-xen-3.2.0/arch/ia64/sn/kernel/setup.c
---- linux-2.6.18.8/arch/ia64/sn/kernel/setup.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/sn/kernel/setup.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/sn/kernel/setup.c linux-2.6.18-xen-3.3.0/arch/ia64/sn/kernel/setup.c
+--- linux-2.6.18.8/arch/ia64/sn/kernel/setup.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/sn/kernel/setup.c 2008-08-21 11:36:07.000000000 +0200
@@ -763,5 +763,13 @@ int sn_prom_feature_available(int id)
return 0;
return test_bit(id, sn_prom_features);
@@ -26642,9 +27103,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/sn/kernel/setup.c linux-2.6.18-xen-3.2.0/arc
+}
EXPORT_SYMBOL(sn_prom_feature_available);
-diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/pcibr/pcibr_provider.c linux-2.6.18-xen-3.2.0/arch/ia64/sn/pci/pcibr/pcibr_provider.c
---- linux-2.6.18.8/arch/ia64/sn/pci/pcibr/pcibr_provider.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/sn/pci/pcibr/pcibr_provider.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/pcibr/pcibr_provider.c linux-2.6.18-xen-3.3.0/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+--- linux-2.6.18.8/arch/ia64/sn/pci/pcibr/pcibr_provider.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/sn/pci/pcibr/pcibr_provider.c 2008-08-21 11:36:07.000000000 +0200
@@ -15,6 +15,7 @@
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>
@@ -26666,9 +27127,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/pcibr/pcibr_provider.c linux-2.6.18-x
spin_lock_init(&soft->pbi_lock);
-diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/tioca_provider.c linux-2.6.18-xen-3.2.0/arch/ia64/sn/pci/tioca_provider.c
---- linux-2.6.18.8/arch/ia64/sn/pci/tioca_provider.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/sn/pci/tioca_provider.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/tioca_provider.c linux-2.6.18-xen-3.3.0/arch/ia64/sn/pci/tioca_provider.c
+--- linux-2.6.18.8/arch/ia64/sn/pci/tioca_provider.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/sn/pci/tioca_provider.c 2008-08-21 11:36:07.000000000 +0200
@@ -611,7 +611,9 @@ tioca_bus_fixup(struct pcibus_bussoft *p
return NULL;
@@ -26680,9 +27141,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/tioca_provider.c linux-2.6.18-xen-3.2
/* init kernel-private area */
-diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/tioce_provider.c linux-2.6.18-xen-3.2.0/arch/ia64/sn/pci/tioce_provider.c
---- linux-2.6.18.8/arch/ia64/sn/pci/tioce_provider.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/sn/pci/tioce_provider.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/tioce_provider.c linux-2.6.18-xen-3.3.0/arch/ia64/sn/pci/tioce_provider.c
+--- linux-2.6.18.8/arch/ia64/sn/pci/tioce_provider.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/sn/pci/tioce_provider.c 2008-08-21 11:36:07.000000000 +0200
@@ -1006,7 +1006,9 @@ tioce_bus_fixup(struct pcibus_bussoft *p
return NULL;
@@ -26694,22 +27155,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/sn/pci/tioce_provider.c linux-2.6.18-xen-3.2
tioce_kern = tioce_kern_init(tioce_common);
if (tioce_kern == NULL) {
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/Makefile linux-2.6.18-xen-3.2.0/arch/ia64/xen/Makefile
---- linux-2.6.18.8/arch/ia64/xen/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/Makefile 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,9 @@
-+#
-+# Makefile for Xen components
-+#
-+
-+obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o \
-+ hypervisor.o util.o xencomm.o xcom_hcall.o \
-+ xcom_privcmd.o xen_dma.o
-+
-+obj-$(CONFIG_IA64_GENERIC) += machvec.o
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypercall.S linux-2.6.18-xen-3.2.0/arch/ia64/xen/hypercall.S
---- linux-2.6.18.8/arch/ia64/xen/hypercall.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/hypercall.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypercall.S linux-2.6.18-xen-3.3.0/arch/ia64/xen/hypercall.S
+--- linux-2.6.18.8/arch/ia64/xen/hypercall.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/hypercall.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,141 @@
+/*
+ * Support routines for Xen hypercalls
@@ -26852,10 +27300,10 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypercall.S linux-2.6.18-xen-3.2.0/arch/
+ br.ret.sptk.many b0
+ ;;
+END(__hypercall)
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypervisor.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/hypervisor.c
---- linux-2.6.18.8/arch/ia64/xen/hypervisor.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/hypervisor.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,1511 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypervisor.c linux-2.6.18-xen-3.3.0/arch/ia64/xen/hypervisor.c
+--- linux-2.6.18.8/arch/ia64/xen/hypervisor.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/hypervisor.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1526 @@
+/******************************************************************************
+ * include/asm-ia64/shadow.h
+ *
@@ -27511,6 +27959,12 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypervisor.c linux-2.6.18-xen-3.2.0/arch
+
+ prot = vma->vm_page_prot;
+ error = remap_pfn_range(vma, addr, gpfn, 1 << PAGE_SHIFT, prot);
++ /*
++ * VM_PFNMAP is set in remap_pfn_range().
++ * Reset the flag to avoid BUG_ON() in do_no_page().
++ */
++ vma->vm_flags &= ~VM_PFNMAP;
++
+ if (error != 0) {
+ error = HYPERVISOR_zap_physmap(gpfn, 0);
+ if (error)
@@ -27564,9 +28018,18 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypervisor.c linux-2.6.18-xen-3.2.0/arch
+static void xen_ia64_privcmd_vma_open(struct vm_area_struct *vma);
+static void xen_ia64_privcmd_vma_close(struct vm_area_struct *vma);
+
++static struct page *
++xen_ia64_privcmd_vma_nopage(struct vm_area_struct *vma,
++ unsigned long address,
++ int *type)
++{
++ return NOPAGE_SIGBUS;
++}
++
+struct vm_operations_struct xen_ia64_privcmd_vm_ops = {
-+ .open = &xen_ia64_privcmd_vma_open,
-+ .close = &xen_ia64_privcmd_vma_close,
++ .open = xen_ia64_privcmd_vma_open,
++ .close = xen_ia64_privcmd_vma_close,
++ .nopage = xen_ia64_privcmd_vma_nopage
+};
+
+static void
@@ -27690,7 +28153,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypervisor.c linux-2.6.18-xen-3.2.0/arch
+ privcmd_range->res = res;
+
+ /* DONTCOPY is essential for Xen as copy_page_range is broken. */
-+ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY | VM_PFNMAP;
++ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
+
+ atomic_set(&privcmd_range->ref_count, 1);
+ privcmd_range->pgoff = vma->vm_pgoff;
@@ -28367,17 +28830,30 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/hypervisor.c linux-2.6.18-xen-3.2.0/arch
+ xen_ia64_enable_opt_feature();
+ /* add more if necessary */
+}
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/machvec.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/machvec.c
---- linux-2.6.18.8/arch/ia64/xen/machvec.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/machvec.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/machvec.c linux-2.6.18-xen-3.3.0/arch/ia64/xen/machvec.c
+--- linux-2.6.18.8/arch/ia64/xen/machvec.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/machvec.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,4 @@
+#define MACHVEC_PLATFORM_NAME xen
+#define MACHVEC_PLATFORM_HEADER <asm/machvec_xen.h>
+#include <asm/machvec_init.h>
+
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/swiotlb.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/swiotlb.c
---- linux-2.6.18.8/arch/ia64/xen/swiotlb.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/swiotlb.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/Makefile linux-2.6.18-xen-3.3.0/arch/ia64/xen/Makefile
+--- linux-2.6.18.8/arch/ia64/xen/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,9 @@
++#
++# Makefile for Xen components
++#
++
++obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o \
++ hypervisor.o util.o xencomm.o xcom_hcall.o \
++ xcom_privcmd.o xcom_asm.o xen_dma.o
++
++obj-$(CONFIG_IA64_GENERIC) += machvec.o
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/swiotlb.c linux-2.6.18-xen-3.3.0/arch/ia64/xen/swiotlb.c
+--- linux-2.6.18.8/arch/ia64/xen/swiotlb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/swiotlb.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,906 @@
+/*
+ * Dynamic DMA mapping support.
@@ -29285,9 +29761,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/swiotlb.c linux-2.6.18-xen-3.2.0/arch/ia
+EXPORT_SYMBOL(swiotlb_alloc_coherent);
+EXPORT_SYMBOL(swiotlb_free_coherent);
+EXPORT_SYMBOL(swiotlb_dma_supported);
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/util.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/util.c
---- linux-2.6.18.8/arch/ia64/xen/util.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/util.c 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/util.c linux-2.6.18-xen-3.3.0/arch/ia64/xen/util.c
+--- linux-2.6.18.8/arch/ia64/xen/util.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/util.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,102 @@
+/******************************************************************************
+ * arch/ia64/xen/util.c
@@ -29391,10 +29867,41 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/util.c linux-2.6.18-xen-3.2.0/arch/ia64/
+ * tab-width: 8
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_hcall.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/xcom_hcall.c
---- linux-2.6.18.8/arch/ia64/xen/xcom_hcall.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xcom_hcall.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,663 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_asm.S linux-2.6.18-xen-3.3.0/arch/ia64/xen/xcom_asm.S
+--- linux-2.6.18.8/arch/ia64/xen/xcom_asm.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xcom_asm.S 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,27 @@
++/*
++ * xencomm suspend support
++ * Support routines for Xen
++ *
++ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
++ */
++#include <asm/asmmacro.h>
++#include <xen/interface/xen.h>
++
++/*
++ * Stub for suspend.
++ * Just force the stacked registers to be written in memory.
++ */
++GLOBAL_ENTRY(xencomm_arch_hypercall_suspend)
++ ;;
++ alloc r20=ar.pfs,0,0,6,0
++ mov r2=__HYPERVISOR_sched_op
++ ;;
++ /* We don't want to deal with RSE. */
++ flushrs
++ mov r33=r32
++ mov r32=2 // SCHEDOP_shutdown
++ ;;
++ break 0x1000
++ ;;
++ br.ret.sptk.many b0
++END(xencomm_arch_hypercall_suspend)
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_hcall.c linux-2.6.18-xen-3.3.0/arch/ia64/xen/xcom_hcall.c
+--- linux-2.6.18.8/arch/ia64/xen/xcom_hcall.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xcom_hcall.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,671 @@
+/*
+ * 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
@@ -29541,6 +30048,16 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_hcall.c linux-2.6.18-xen-3.2.0/arch
+ case PHYSDEVOP_irq_status_query:
+ argsize = sizeof(physdev_irq_status_query_t);
+ break;
++ case PHYSDEVOP_manage_pci_add:
++ case PHYSDEVOP_manage_pci_remove:
++ argsize = sizeof(physdev_manage_pci_t);
++ break;
++ case PHYSDEVOP_map_pirq:
++ argsize = sizeof(physdev_map_pirq_t);
++ break;
++ case PHYSDEVOP_unmap_pirq:
++ argsize = sizeof(physdev_unmap_pirq_t);
++ break;
+
+ default:
+ printk("%s: unknown physdev op %d\n", __func__, cmd);
@@ -29881,7 +30398,6 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_hcall.c linux-2.6.18-xen-3.2.0/arch
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_hvm_op);
+
-+#ifndef CONFIG_VMX_GUEST
+int
+xencomm_hypercall_suspend(unsigned long srec)
+{
@@ -29892,7 +30408,6 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_hcall.c linux-2.6.18-xen-3.2.0/arch
+ return xencomm_arch_hypercall_suspend(
+ xencomm_map_no_alloc(&arg, sizeof(arg)));
+}
-+#endif
+
+int
+xencomm_hypercall_xenoprof_op(int op, void *arg)
@@ -30058,10 +30573,10 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_hcall.c linux-2.6.18-xen-3.2.0/arch
+
+ return xencomm_arch_hypercall_kexec_op(cmd, desc);
+}
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/xcom_privcmd.c
---- linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xcom_privcmd.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,823 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.3.0/arch/ia64/xen/xcom_privcmd.c
+--- linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xcom_privcmd.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,902 @@
+/*
+ * 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
@@ -30175,6 +30690,7 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.2.0/ar
+ break;
+ case XEN_SYSCTL_tbuf_op:
+ case XEN_SYSCTL_sched_id:
++ case XEN_SYSCTL_availheap:
+ break;
+ case XEN_SYSCTL_perfc_op:
+ {
@@ -30390,6 +30906,8 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.2.0/ar
+ case XEN_DOMCTL_settimeoffset:
+ case XEN_DOMCTL_sendtrigger:
+ case XEN_DOMCTL_set_opt_feature:
++ case XEN_DOMCTL_assign_device:
++ case XEN_DOMCTL_subscribe:
+ break;
+ case XEN_DOMCTL_pin_mem_cacheattr:
+ return -ENOSYS;
@@ -30500,15 +31018,18 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.2.0/ar
+ * may cause the soft lockup warning.
+ * In order to avoid the warning, we limit
+ * the number of extents and repeat the hypercall.
-+ * The following value is determined by experimentation.
-+ * If the following limit causes soft lockup warning,
++ * The following value is determined by evaluation.
++ * Time of one hypercall should be smaller than
++ * a vcpu time slice. The time with current
++ * MEMORYOP_MAX_EXTENTS is around 5 msec.
++ * If the following limit causes some issues,
+ * we should decrease this value.
+ *
+ * Another way would be that start with small value and
+ * increase adoptively measuring hypercall time.
+ * It might be over-kill.
+ */
-+#define MEMORYOP_MAX_EXTENTS (MEMORYOP_XENCOMM_LIMIT / 4)
++#define MEMORYOP_MAX_EXTENTS (MEMORYOP_XENCOMM_LIMIT / 512)
+
+ while (nr_extents > 0) {
+ xen_ulong_t nr_tmp = nr_extents;
@@ -30724,6 +31245,41 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.2.0/ar
+}
+
+static int
++xencomm_privcmd_hvm_op_track_dirty_vram(privcmd_hypercall_t *hypercall)
++{
++#if 1
++ /*
++ * At this moment HVMOP_track_dirty_vram isn't implemented
++ * on xen/ia64 so that it just returns -ENOSYS.
++ * Don't issue hypercall to get -ENOSYS.
++ * When the hypercall is implemented, enable the following codes.
++ */
++ return -ENOSYS;
++#else
++ int cmd = hypercall->arg[0];
++ struct xen_hvm_track_dirty_vram *user_op = (void*)hypercall->arg[1];
++ struct xen_hvm_track_dirty_vram kern_op;
++ struct xencomm_handle *desc;
++ struct xencomm_handle *bitmap_desc;
++ int ret;
++
++ BUG_ON(cmd != HVMOP_track_dirty_vram);
++ if (copy_from_user(&kern_op, user_op, sizeof(kern_op)))
++ return -EFAULT;
++ desc = xencomm_map_no_alloc(&kern_op, sizeof(kern_op));
++ bitmap_desc = xencomm_map(xen_guest_handle(kern_op.dirty_bitmap),
++ kern_op.nr * sizeof(uint8_t));
++ if (bitmap_desc == NULL)
++ return -ENOMEM;
++ set_xen_guest_handle(kern_op.dirty_bitmap, (void*)bitmap_desc);
++ ret = xencomm_arch_hypercall_hvm_op(cmd, desc);
++ xencomm_free(bitmap_desc);
++
++ return ret;
++#endif
++}
++
++static int
+xencomm_privcmd_hvm_op(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
@@ -30745,6 +31301,12 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.2.0/ar
+ case HVMOP_set_pci_link_route:
+ argsize = sizeof(xen_hvm_set_pci_link_route_t);
+ break;
++ case HVMOP_set_mem_type:
++ argsize = sizeof(xen_hvm_set_mem_type_t);
++ break;
++
++ case HVMOP_track_dirty_vram:
++ return xencomm_privcmd_hvm_op_track_dirty_vram(hypercall);
+
+ default:
+ printk("%s: unknown HVMOP %d\n", __func__, cmd);
@@ -30853,6 +31415,36 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.2.0/ar
+ return ret;
+}
+
++static int
++xencomm_privcmd_ia64_physdev_op(privcmd_hypercall_t *hypercall)
++{
++ int cmd = hypercall->arg[0];
++ struct xencomm_handle *desc;
++ unsigned int argsize;
++ int ret;
++
++ switch (cmd) {
++ case PHYSDEVOP_map_pirq:
++ argsize = sizeof(physdev_map_pirq_t);
++ break;
++ case PHYSDEVOP_unmap_pirq:
++ argsize = sizeof(physdev_unmap_pirq_t);
++ break;
++ default:
++ printk("%s: unknown PHYSDEVOP %d\n", __func__, cmd);
++ return -EINVAL;
++ }
++
++ desc = xencomm_map((void *)hypercall->arg[1], argsize);
++ if ((void *)hypercall->arg[1] != NULL && argsize > 0 && desc == NULL)
++ return -ENOMEM;
++
++ ret = xencomm_arch_hypercall_physdev_op(cmd, desc);
++
++ xencomm_free(desc);
++ return ret;
++}
++
+int
+privcmd_hypercall(privcmd_hypercall_t *hypercall)
+{
@@ -30879,16 +31471,131 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xcom_privcmd.c linux-2.6.18-xen-3.2.0/ar
+ return xencomm_privcmd_ia64_dom0vp_op(hypercall);
+ case __HYPERVISOR_ia64_debug_op:
+ return xencomm_privcmd_ia64_debug_op(hypercall);
++ case __HYPERVISOR_physdev_op:
++ return xencomm_privcmd_ia64_physdev_op(hypercall);
+ default:
+ printk("%s: unknown hcall (%ld)\n", __func__, hypercall->op);
+ return -ENOSYS;
+ }
+}
+
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xen_dma.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/xen_dma.c
---- linux-2.6.18.8/arch/ia64/xen/xen_dma.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xen_dma.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,155 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xencomm.c linux-2.6.18-xen-3.3.0/arch/ia64/xen/xencomm.c
+--- linux-2.6.18.8/arch/ia64/xen/xencomm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xencomm.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,109 @@
++/*
++ * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation
++ *
++ * 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; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/gfp.h>
++#include <linux/mm.h>
++#include <xen/interface/xen.h>
++#include <asm/page.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#include <asm/xen/xencomm.h>
++
++static unsigned long kernel_start_pa;
++
++void
++xencomm_initialize (void)
++{
++ kernel_start_pa = KERNEL_START - ia64_tpa(KERNEL_START);
++}
++
++/* Translate virtual address to physical address. */
++unsigned long
++xencomm_vtop(unsigned long vaddr)
++{
++#ifndef CONFIG_VMX_GUEST
++ struct page *page;
++ struct vm_area_struct *vma;
++#endif
++
++ if (vaddr == 0)
++ return 0;
++
++#ifdef __ia64__
++ if (REGION_NUMBER(vaddr) == 5) {
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++ pte_t *ptep;
++
++ /* On ia64, TASK_SIZE refers to current. It is not initialized
++ during boot.
++ Furthermore the kernel is relocatable and __pa() doesn't
++ work on addresses. */
++ if (vaddr >= KERNEL_START
++ && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) {
++ return vaddr - kernel_start_pa;
++ }
++
++ /* In kernel area -- virtually mapped. */
++ pgd = pgd_offset_k(vaddr);
++ if (pgd_none(*pgd) || pgd_bad(*pgd))
++ return ~0UL;
++
++ pud = pud_offset(pgd, vaddr);
++ if (pud_none(*pud) || pud_bad(*pud))
++ return ~0UL;
++
++ pmd = pmd_offset(pud, vaddr);
++ if (pmd_none(*pmd) || pmd_bad(*pmd))
++ return ~0UL;
++
++ ptep = pte_offset_kernel(pmd, vaddr);
++ if (!ptep)
++ return ~0UL;
++
++ return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK);
++ }
++#endif
++
++ if (vaddr > TASK_SIZE) {
++ /* kernel address */
++ return __pa(vaddr);
++ }
++
++
++#ifdef CONFIG_VMX_GUEST
++ /* No privcmd within vmx guest. */
++ return ~0UL;
++#else
++ /* XXX double-check (lack of) locking */
++ vma = find_extend_vma(current->mm, vaddr);
++ if (!vma)
++ return ~0UL;
++
++ /* We assume the page is modified. */
++ page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH);
++ if (!page)
++ return ~0UL;
++
++ return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
++#endif
++}
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xen_dma.c linux-2.6.18-xen-3.3.0/arch/ia64/xen/xen_dma.c
+--- linux-2.6.18.8/arch/ia64/xen/xen_dma.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xen_dma.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ * Alex Williamson <alex.williamson@hp.com>
@@ -30928,6 +31635,41 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xen_dma.c linux-2.6.18-xen-3.2.0/arch/ia
+ } \
+} while (0)
+
++static int check_pages_physically_contiguous(unsigned long pfn,
++ unsigned int offset,
++ size_t length)
++{
++ unsigned long next_bus;
++ int i;
++ int nr_pages;
++
++ next_bus = pfn_to_mfn_for_dma(pfn);
++ nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT;
++
++ for (i = 1; i < nr_pages; i++) {
++ if (pfn_to_mfn_for_dma(++pfn) != ++next_bus)
++ return 0;
++ }
++ return 1;
++}
++
++int range_straddles_page_boundary(paddr_t p, size_t size)
++{
++ extern unsigned long *contiguous_bitmap;
++ unsigned long pfn = p >> PAGE_SHIFT;
++ unsigned int offset = p & ~PAGE_MASK;
++
++ if (!is_running_on_xen())
++ return 0;
++
++ if (offset + size <= PAGE_SIZE)
++ return 0;
++ if (test_bit(pfn, contiguous_bitmap))
++ return 0;
++ if (check_pages_physically_contiguous(pfn, offset, size))
++ return 0;
++ return 1;
++}
+
+/*
+ * This should be broken out of swiotlb and put in a common place
@@ -31044,122 +31786,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xen_dma.c linux-2.6.18-xen-3.2.0/arch/ia
+ gnttab_dma_unmap_page(dma_addr);
+}
+EXPORT_SYMBOL(xen_unmap_single);
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xencomm.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/xencomm.c
---- linux-2.6.18.8/arch/ia64/xen/xencomm.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xencomm.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,109 @@
-+/*
-+ * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation
-+ *
-+ * 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; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/gfp.h>
-+#include <linux/mm.h>
-+#include <xen/interface/xen.h>
-+#include <asm/page.h>
-+
-+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
-+#include <xen/platform-compat.h>
-+#endif
-+
-+#include <asm/xen/xencomm.h>
-+
-+static unsigned long kernel_start_pa;
-+
-+void
-+xencomm_initialize (void)
-+{
-+ kernel_start_pa = KERNEL_START - ia64_tpa(KERNEL_START);
-+}
-+
-+/* Translate virtual address to physical address. */
-+unsigned long
-+xencomm_vtop(unsigned long vaddr)
-+{
-+#ifndef CONFIG_VMX_GUEST
-+ struct page *page;
-+ struct vm_area_struct *vma;
-+#endif
-+
-+ if (vaddr == 0)
-+ return 0;
-+
-+#ifdef __ia64__
-+ if (REGION_NUMBER(vaddr) == 5) {
-+ pgd_t *pgd;
-+ pud_t *pud;
-+ pmd_t *pmd;
-+ pte_t *ptep;
-+
-+ /* On ia64, TASK_SIZE refers to current. It is not initialized
-+ during boot.
-+ Furthermore the kernel is relocatable and __pa() doesn't
-+ work on addresses. */
-+ if (vaddr >= KERNEL_START
-+ && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) {
-+ return vaddr - kernel_start_pa;
-+ }
-+
-+ /* In kernel area -- virtually mapped. */
-+ pgd = pgd_offset_k(vaddr);
-+ if (pgd_none(*pgd) || pgd_bad(*pgd))
-+ return ~0UL;
-+
-+ pud = pud_offset(pgd, vaddr);
-+ if (pud_none(*pud) || pud_bad(*pud))
-+ return ~0UL;
-+
-+ pmd = pmd_offset(pud, vaddr);
-+ if (pmd_none(*pmd) || pmd_bad(*pmd))
-+ return ~0UL;
-+
-+ ptep = pte_offset_kernel(pmd, vaddr);
-+ if (!ptep)
-+ return ~0UL;
-+
-+ return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK);
-+ }
-+#endif
-+
-+ if (vaddr > TASK_SIZE) {
-+ /* kernel address */
-+ return __pa(vaddr);
-+ }
-+
-+
-+#ifdef CONFIG_VMX_GUEST
-+ /* No privcmd within vmx guest. */
-+ return ~0UL;
-+#else
-+ /* XXX double-check (lack of) locking */
-+ vma = find_extend_vma(current->mm, vaddr);
-+ if (!vma)
-+ return ~0UL;
-+
-+ /* We assume the page is modified. */
-+ page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH);
-+ if (!page)
-+ return ~0UL;
-+
-+ return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
-+#endif
-+}
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenentry.S linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenentry.S
---- linux-2.6.18.8/arch/ia64/xen/xenentry.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenentry.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenentry.S linux-2.6.18-xen-3.3.0/arch/ia64/xen/xenentry.S
+--- linux-2.6.18.8/arch/ia64/xen/xenentry.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xenentry.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,931 @@
+/*
+ * ia64/xen/entry.S
@@ -32092,33 +32721,10 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenentry.S linux-2.6.18-xen-3.2.0/arch/i
+#else
+END(ia64_leave_kernel)
+#endif
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenhpski.c linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenhpski.c
---- linux-2.6.18.8/arch/ia64/xen/xenhpski.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenhpski.c 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,19 @@
-+#include <linux/kernel.h>
-+#include <asm/hypervisor.h>
-+
-+int
-+running_on_sim(void)
-+{
-+ int i;
-+ long cpuid[6];
-+
-+ for (i = 0; i < 5; ++i)
-+ cpuid[i] = xen_get_cpuid(i);
-+ if ((cpuid[0] & 0xff) != 'H') return 0;
-+ if ((cpuid[3] & 0xff) != 0x4) return 0;
-+ if (((cpuid[3] >> 8) & 0xff) != 0x0) return 0;
-+ if (((cpuid[3] >> 16) & 0xff) != 0x0) return 0;
-+ if (((cpuid[3] >> 24) & 0x7) != 0x7) return 0;
-+ return 1;
-+}
-+
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenivt.S linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenivt.S
---- linux-2.6.18.8/arch/ia64/xen/xenivt.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenivt.S 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,2177 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenivt.S linux-2.6.18-xen-3.3.0/arch/ia64/xen/xenivt.S
+--- linux-2.6.18.8/arch/ia64/xen/xenivt.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xenivt.S 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2178 @@
+/*
+ * arch/ia64/xen/ivt.S
+ *
@@ -32817,16 +33423,17 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenivt.S linux-2.6.18-xen-3.2.0/arch/ia6
+ st4 [r3]=r14 // vpsr.ic = 1
+ adds r3=8,r2 // set up second base pointer
+ ;;
++ sum PSR_DEFAULT_BITS
+#else
+ mov out0=cr.ifa
+ mov out1=cr.isr
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic | PSR_DEFAULT_BITS
++#endif
+ ;;
+ srlz.i // guarantee that interruption collectin is on
+ ;;
-+#endif
+#ifdef CONFIG_XEN
+
+#define MASK_TO_PEND_OFS (-1)
@@ -34296,9 +34903,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenivt.S linux-2.6.18-xen-3.2.0/arch/ia6
+
+
+#endif
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenminstate.h linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenminstate.h
---- linux-2.6.18.8/arch/ia64/xen/xenminstate.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenminstate.h 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenminstate.h linux-2.6.18-xen-3.3.0/arch/ia64/xen/xenminstate.h
+--- linux-2.6.18.8/arch/ia64/xen/xenminstate.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xenminstate.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,358 @@
+#include <asm/cache.h>
+
@@ -34658,9 +35265,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenminstate.h linux-2.6.18-xen-3.2.0/arc
+#else
+#define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, )
+#endif
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenpal.S linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenpal.S
---- linux-2.6.18.8/arch/ia64/xen/xenpal.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xenpal.S 2008-02-15 16:21:49.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenpal.S linux-2.6.18-xen-3.3.0/arch/ia64/xen/xenpal.S
+--- linux-2.6.18.8/arch/ia64/xen/xenpal.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xenpal.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,85 @@
+/*
+ * ia64/xen/xenpal.S
@@ -34747,10 +35354,10 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xenpal.S linux-2.6.18-xen-3.2.0/arch/ia6
+ srlz.d // seralize restoration of psr.l
+ br.ret.sptk.many b0
+END(xen_pal_call_static)
-diff -rpuN linux-2.6.18.8/arch/ia64/xen/xensetup.S linux-2.6.18-xen-3.2.0/arch/ia64/xen/xensetup.S
---- linux-2.6.18.8/arch/ia64/xen/xensetup.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/ia64/xen/xensetup.S 2008-02-15 16:21:49.000000000 -0800
-@@ -0,0 +1,59 @@
+diff -rpuN linux-2.6.18.8/arch/ia64/xen/xensetup.S linux-2.6.18-xen-3.3.0/arch/ia64/xen/xensetup.S
+--- linux-2.6.18.8/arch/ia64/xen/xensetup.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/ia64/xen/xensetup.S 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,40 @@
+/*
+ * Support routines for Xen
+ *
@@ -34791,93 +35398,9 @@ diff -rpuN linux-2.6.18.8/arch/ia64/xen/xensetup.S linux-2.6.18-xen-3.2.0/arch/i
+ br.ret.sptk.many rp
+ ;;
+END(early_xen_setup)
-+
-+#include <xen/interface/xen.h>
-+
-+/* Stub for suspend.
-+ Just force the stacked registers to be written in memory. */
-+GLOBAL_ENTRY(xencomm_arch_hypercall_suspend)
-+ ;;
-+ alloc r20=ar.pfs,0,0,6,0
-+ mov r2=__HYPERVISOR_sched_op
-+ ;;
-+ /* We don't want to deal with RSE. */
-+ flushrs
-+ mov r33=r32
-+ mov r32=2 // SCHEDOP_shutdown
-+ ;;
-+ break 0x1000
-+ ;;
-+ br.ret.sptk.many b0
-+END(xencomm_arch_hypercall_suspend)
-diff -rpuN linux-2.6.18.8/arch/powerpc/Kconfig linux-2.6.18-xen-3.2.0/arch/powerpc/Kconfig
---- linux-2.6.18.8/arch/powerpc/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/Kconfig 2008-02-15 16:21:51.000000000 -0800
-@@ -439,6 +439,17 @@ config UDBG_RTAS_CONSOLE
- bool
- default n
-
-+config PPC_XEN
-+ bool "Enable Xen compatible kernel"
-+ depends on PPC_MULTIPLATFORM && PPC64 && PPC_MAPLE && PPC_PSERIES && SMP
-+ select XEN
-+ select XEN_PRIVILEGED_GUEST
-+ select XEN_UNPRIVILEGED_GUEST
-+ select XEN_XENCOMM
-+
-+ help
-+ This option will compile a kernel compatible with Xen hypervisor
-+
- config XICS
- depends on PPC_PSERIES
- bool
-@@ -1080,6 +1091,8 @@ source "arch/powerpc/Kconfig.debug"
-
- source "security/Kconfig"
-
-+source "drivers/xen/Kconfig"
-+
- config KEYS_COMPAT
- bool
- depends on COMPAT && KEYS
-diff -rpuN linux-2.6.18.8/arch/powerpc/Kconfig.debug linux-2.6.18-xen-3.2.0/arch/powerpc/Kconfig.debug
---- linux-2.6.18.8/arch/powerpc/Kconfig.debug 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/Kconfig.debug 2008-02-15 16:21:51.000000000 -0800
-@@ -160,6 +160,20 @@ config PPC_EARLY_DEBUG_ISERIES
- Select this to enable early debugging for legacy iSeries. You need
- to hit "Ctrl-x Ctrl-x" to see the messages on the console.
-
-+config PPC_EARLY_DEBUG_XEN_DOM0
-+ bool "Xen Dom0 Console"
-+ depends on PPC_XEN
-+ help
-+ Select this to enable early debugging for Xen Dom0. Setting
-+ this will result in a kernel that may not work as a DomU.
-+
-+config PPC_EARLY_DEBUG_XEN_DOMU
-+ bool "Xen DomU Console"
-+ depends on PPC_XEN && XEN_UNPRIVILEGED_GUEST
-+ help
-+ Select this to enable early debugging for Xen DomU. Setting
-+ this will result in a kernel that may not work as a Dom0.
-+
- endchoice
-
- endmenu
-diff -rpuN linux-2.6.18.8/arch/powerpc/Makefile linux-2.6.18-xen-3.2.0/arch/powerpc/Makefile
---- linux-2.6.18.8/arch/powerpc/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/Makefile 2008-02-15 16:21:51.000000000 -0800
-@@ -65,6 +65,7 @@ CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARC
- AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
- CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc
- CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple
-+CFLAGS-$(CONFIG_PPC_XEN) += -Iinclude/asm-$(ARCH)/xen
- CPPFLAGS += $(CPPFLAGS-y)
- AFLAGS += $(AFLAGS-y)
- CFLAGS += -msoft-float -pipe $(CFLAGS-y)
-diff -rpuN linux-2.6.18.8/arch/powerpc/boot/Makefile linux-2.6.18-xen-3.2.0/arch/powerpc/boot/Makefile
---- linux-2.6.18.8/arch/powerpc/boot/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/boot/Makefile 2008-02-15 16:21:51.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/boot/Makefile linux-2.6.18-xen-3.3.0/arch/powerpc/boot/Makefile
+--- linux-2.6.18.8/arch/powerpc/boot/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/boot/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -36,8 +36,11 @@ zliblinuxheader := zlib.h zconf.h zutil.
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
@@ -34890,9 +35413,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/boot/Makefile linux-2.6.18-xen-3.2.0/arch
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
-diff -rpuN linux-2.6.18.8/arch/powerpc/boot/xen_guest.S linux-2.6.18-xen-3.2.0/arch/powerpc/boot/xen_guest.S
---- linux-2.6.18.8/arch/powerpc/boot/xen_guest.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/boot/xen_guest.S 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/boot/xen_guest.S linux-2.6.18-xen-3.3.0/arch/powerpc/boot/xen_guest.S
+--- linux-2.6.18.8/arch/powerpc/boot/xen_guest.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/boot/xen_guest.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,7 @@
+ .section __xen_guest
+ .ascii "GUEST_OS=linux"
@@ -34901,9 +35424,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/boot/xen_guest.S linux-2.6.18-xen-3.2.0/a
+ .ascii ",VIRT_BASE=0x0"
+ .ascii ",LOADER=generic"
+ .byte 0
-diff -rpuN linux-2.6.18.8/arch/powerpc/configs/xen_maple_defconfig linux-2.6.18-xen-3.2.0/arch/powerpc/configs/xen_maple_defconfig
---- linux-2.6.18.8/arch/powerpc/configs/xen_maple_defconfig 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/configs/xen_maple_defconfig 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/configs/xen_maple_defconfig linux-2.6.18-xen-3.3.0/arch/powerpc/configs/xen_maple_defconfig
+--- linux-2.6.18.8/arch/powerpc/configs/xen_maple_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/configs/xen_maple_defconfig 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1342 @@
+#
+# Automatically generated make config: don't edit
@@ -36247,9 +36770,63 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/configs/xen_maple_defconfig linux-2.6.18-
+#
+# Hardware crypto devices
+#
-diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/cpu_setup_power4.S linux-2.6.18-xen-3.2.0/arch/powerpc/kernel/cpu_setup_power4.S
---- linux-2.6.18.8/arch/powerpc/kernel/cpu_setup_power4.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/kernel/cpu_setup_power4.S 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/Kconfig linux-2.6.18-xen-3.3.0/arch/powerpc/Kconfig
+--- linux-2.6.18.8/arch/powerpc/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -439,6 +439,17 @@ config UDBG_RTAS_CONSOLE
+ bool
+ default n
+
++config PPC_XEN
++ bool "Enable Xen compatible kernel"
++ depends on PPC_MULTIPLATFORM && PPC64 && PPC_MAPLE && PPC_PSERIES && SMP
++ select XEN
++ select XEN_PRIVILEGED_GUEST
++ select XEN_UNPRIVILEGED_GUEST
++ select XEN_XENCOMM
++
++ help
++ This option will compile a kernel compatible with Xen hypervisor
++
+ config XICS
+ depends on PPC_PSERIES
+ bool
+@@ -1080,6 +1091,8 @@ source "arch/powerpc/Kconfig.debug"
+
+ source "security/Kconfig"
+
++source "drivers/xen/Kconfig"
++
+ config KEYS_COMPAT
+ bool
+ depends on COMPAT && KEYS
+diff -rpuN linux-2.6.18.8/arch/powerpc/Kconfig.debug linux-2.6.18-xen-3.3.0/arch/powerpc/Kconfig.debug
+--- linux-2.6.18.8/arch/powerpc/Kconfig.debug 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/Kconfig.debug 2008-08-21 11:36:07.000000000 +0200
+@@ -160,6 +160,20 @@ config PPC_EARLY_DEBUG_ISERIES
+ Select this to enable early debugging for legacy iSeries. You need
+ to hit "Ctrl-x Ctrl-x" to see the messages on the console.
+
++config PPC_EARLY_DEBUG_XEN_DOM0
++ bool "Xen Dom0 Console"
++ depends on PPC_XEN
++ help
++ Select this to enable early debugging for Xen Dom0. Setting
++ this will result in a kernel that may not work as a DomU.
++
++config PPC_EARLY_DEBUG_XEN_DOMU
++ bool "Xen DomU Console"
++ depends on PPC_XEN && XEN_UNPRIVILEGED_GUEST
++ help
++ Select this to enable early debugging for Xen DomU. Setting
++ this will result in a kernel that may not work as a Dom0.
++
+ endchoice
+
+ endmenu
+diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/cpu_setup_power4.S linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/cpu_setup_power4.S
+--- linux-2.6.18.8/arch/powerpc/kernel/cpu_setup_power4.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/cpu_setup_power4.S 2008-08-21 11:36:07.000000000 +0200
@@ -73,6 +73,13 @@ _GLOBAL(__970_cpu_preinit)
blr
@@ -36264,9 +36841,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/cpu_setup_power4.S linux-2.6.18-xe
mfspr r0,SPRN_HID0
li r11,5 /* clear DOZE and SLEEP */
rldimi r0,r11,52,8 /* set NAP and DPM */
-diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/prom_init.c linux-2.6.18-xen-3.2.0/arch/powerpc/kernel/prom_init.c
---- linux-2.6.18.8/arch/powerpc/kernel/prom_init.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/kernel/prom_init.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/prom_init.c linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/prom_init.c
+--- linux-2.6.18.8/arch/powerpc/kernel/prom_init.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/prom_init.c 2008-08-21 11:36:07.000000000 +0200
@@ -188,6 +188,7 @@ static unsigned long __initdata prom_tce
#define PLATFORM_LPAR 0x0001
#define PLATFORM_POWERMAC 0x0400
@@ -36322,9 +36899,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/prom_init.c linux-2.6.18-xen-3.2.0
/*
* On non-powermacs, try to instantiate RTAS and puts all CPUs
-diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/setup-common.c linux-2.6.18-xen-3.2.0/arch/powerpc/kernel/setup-common.c
---- linux-2.6.18.8/arch/powerpc/kernel/setup-common.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/kernel/setup-common.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/setup-common.c linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/setup-common.c
+--- linux-2.6.18.8/arch/powerpc/kernel/setup-common.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/setup-common.c 2008-08-21 11:36:07.000000000 +0200
@@ -387,6 +387,12 @@ void __init smp_setup_cpu_maps(void)
}
}
@@ -36338,9 +36915,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/setup-common.c linux-2.6.18-xen-3.
#ifdef CONFIG_PPC64
/*
* On pSeries LPAR, we need to know how many cpus
-diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/udbg.c linux-2.6.18-xen-3.2.0/arch/powerpc/kernel/udbg.c
---- linux-2.6.18.8/arch/powerpc/kernel/udbg.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/kernel/udbg.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/udbg.c linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/udbg.c
+--- linux-2.6.18.8/arch/powerpc/kernel/udbg.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/udbg.c 2008-08-21 11:36:07.000000000 +0200
@@ -45,6 +45,9 @@ void __init udbg_early_init(void)
#elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES)
/* For iSeries - hit Ctrl-x Ctrl-x to see the output */
@@ -36351,9 +36928,37 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/udbg.c linux-2.6.18-xen-3.2.0/arch
#endif
}
-diff -rpuN linux-2.6.18.8/arch/powerpc/mm/slb_low.S linux-2.6.18-xen-3.2.0/arch/powerpc/mm/slb_low.S
---- linux-2.6.18.8/arch/powerpc/mm/slb_low.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/mm/slb_low.S 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/kernel/vdso.c linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/vdso.c
+--- linux-2.6.18.8/arch/powerpc/kernel/vdso.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/kernel/vdso.c 2008-08-21 11:36:07.000000000 +0200
+@@ -282,6 +282,13 @@ int arch_setup_additional_pages(struct l
+ * pages though
+ */
+ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
++ /*
++ * Make sure the vDSO gets into every core dump.
++ * Dumping its contents makes post-mortem fully interpretable later
++ * without matching up the same kernel and hardware config to see
++ * what PC values meant.
++ */
++ vma->vm_flags |= VM_ALWAYSDUMP;
+ vma->vm_flags |= mm->def_flags;
+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
+ vma->vm_ops = &vdso_vmops;
+diff -rpuN linux-2.6.18.8/arch/powerpc/Makefile linux-2.6.18-xen-3.3.0/arch/powerpc/Makefile
+--- linux-2.6.18.8/arch/powerpc/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -65,6 +65,7 @@ CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARC
+ AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
+ CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc
+ CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple
++CFLAGS-$(CONFIG_PPC_XEN) += -Iinclude/asm-$(ARCH)/xen
+ CPPFLAGS += $(CPPFLAGS-y)
+ AFLAGS += $(AFLAGS-y)
+ CFLAGS += -msoft-float -pipe $(CFLAGS-y)
+diff -rpuN linux-2.6.18.8/arch/powerpc/mm/slb_low.S linux-2.6.18-xen-3.3.0/arch/powerpc/mm/slb_low.S
+--- linux-2.6.18.8/arch/powerpc/mm/slb_low.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/mm/slb_low.S 2008-08-21 11:36:07.000000000 +0200
@@ -51,6 +51,23 @@ _GLOBAL(slb_allocate_realmode)
*/
bne cr7,1f
@@ -36378,9 +36983,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/mm/slb_low.S linux-2.6.18-xen-3.2.0/arch/
/* Linear mapping encoding bits, the "li" instruction below will
* be patched by the kernel at boot
*/
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/Makefile linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/Makefile
---- linux-2.6.18.8/arch/powerpc/platforms/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/Makefile 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/Makefile linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/Makefile
+--- linux-2.6.18.8/arch/powerpc/platforms/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -12,6 +12,8 @@ obj-$(CONFIG_PPC_85xx) += 85xx/
obj-$(CONFIG_PPC_86xx) += 86xx/
obj-$(CONFIG_PPC_PSERIES) += pseries/
@@ -36390,9 +36995,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/Makefile linux-2.6.18-xen-3.2.0
obj-$(CONFIG_PPC_MAPLE) += maple/
obj-$(CONFIG_PPC_CELL) += cell/
obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/pseries/iommu.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/pseries/iommu.c
---- linux-2.6.18.8/arch/powerpc/platforms/pseries/iommu.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/pseries/iommu.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/pseries/iommu.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/pseries/iommu.c
+--- linux-2.6.18.8/arch/powerpc/platforms/pseries/iommu.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/pseries/iommu.c 2008-08-21 11:36:07.000000000 +0200
@@ -531,6 +531,17 @@ static void iommu_dev_setup_pSeriesLP(st
* already allocated.
*/
@@ -36411,33 +37016,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/pseries/iommu.c linux-2.6.18-xe
for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
pdn = pdn->parent) {
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/Makefile linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/Makefile
---- linux-2.6.18.8/arch/powerpc/platforms/xen/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/Makefile 2008-02-15 16:21:53.000000000 -0800
-@@ -0,0 +1,20 @@
-+obj-y += gnttab.o
-+obj-y += hcall.o
-+obj-y += reboot.o
-+obj-y += setup.o
-+obj-y += smp.o
-+obj-y += time.o
-+obj-y += udbg_xen.o
-+obj-y += xen_guest.o
-+obj-y += xencomm.o
-+
-+# we need the latest __XEN_INTERFACE_VERSION__ (see xen-compat.h)
-+CFLAGS_hcall.o += -D__XEN_TOOLS__
-+
-+ifndef CONFIG_XEN_BALLOON
-+obj-y += balloon.o
-+endif
-+
-+ifndef CONFIG_XEN_UTIL
-+obj-y += util.o
-+endif
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/balloon.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/balloon.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/balloon.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/balloon.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/balloon.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/balloon.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/balloon.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/balloon.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,82 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -36521,9 +37102,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/balloon.c linux-2.6.18-xen-
+EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
+EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
+EXPORT_SYMBOL_GPL(balloon_release_driver_page);
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/gnttab.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/gnttab.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/gnttab.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/gnttab.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/gnttab.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/gnttab.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/gnttab.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/gnttab.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,468 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -36993,9 +37574,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/gnttab.c linux-2.6.18-xen-3
+
+ return shared;
+}
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/hcall.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/hcall.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/hcall.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/hcall.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/hcall.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/hcall.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/hcall.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/hcall.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,891 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -37888,9 +38469,33 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/hcall.c linux-2.6.18-xen-3.
+
+ return rc;
+}
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/reboot.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/reboot.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/reboot.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/reboot.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/Makefile linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/Makefile
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,20 @@
++obj-y += gnttab.o
++obj-y += hcall.o
++obj-y += reboot.o
++obj-y += setup.o
++obj-y += smp.o
++obj-y += time.o
++obj-y += udbg_xen.o
++obj-y += xen_guest.o
++obj-y += xencomm.o
++
++# we need the latest __XEN_INTERFACE_VERSION__ (see xen-compat.h)
++CFLAGS_hcall.o += -D__XEN_TOOLS__
++
++ifndef CONFIG_XEN_BALLOON
++obj-y += balloon.o
++endif
++
++ifndef CONFIG_XEN_UTIL
++obj-y += util.o
++endif
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/reboot.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/reboot.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/reboot.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/reboot.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,53 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -37945,9 +38550,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/reboot.c linux-2.6.18-xen-3
+ ppc_md.halt = domain_machine_power_off;
+ }
+}
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/setup.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/setup.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/setup.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/setup.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/setup.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/setup.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/setup.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,336 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -38285,9 +38890,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/setup.c linux-2.6.18-xen-3.
+ .machine_crash_shutdown = xen_machine_crash_shutdown,
+#endif
+};
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/setup.h linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/setup.h
---- linux-2.6.18.8/arch/powerpc/platforms/xen/setup.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/setup.h 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/setup.h linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/setup.h
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/setup.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/setup.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -38336,9 +38941,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/setup.h linux-2.6.18-xen-3.
+
+extern void __init xen_setup_time(struct machdep_calls *host_md);
+extern void xen_setup_smp(void);
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/smp.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/smp.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/smp.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/smp.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/smp.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/smp.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/smp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/smp.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,444 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -38784,9 +39389,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/smp.c linux-2.6.18-xen-3.2.
+ xen_boot_secondary_vcpus();
+ smp_release_cpus();
+}
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/time.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/time.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/time.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/time.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/time.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/time.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/time.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,114 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -38902,9 +39507,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/time.c linux-2.6.18-xen-3.2
+ ppc_md.get_rtc_time = xen_get_rtc_time;
+ host_md_get_rtc_time = host_md->get_rtc_time;
+}
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/udbg_xen.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/udbg_xen.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/udbg_xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/udbg_xen.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/udbg_xen.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/udbg_xen.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/udbg_xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/udbg_xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,164 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -39070,9 +39675,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/udbg_xen.c linux-2.6.18-xen
+ intf = (struct xencons_interface *)mfn_to_virt(__console_mfn);
+ }
+}
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/util.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/util.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/util.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/util.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/util.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/util.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/util.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/util.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,70 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -39144,40 +39749,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/util.c linux-2.6.18-xen-3.2
+ preempt_enable();
+}
+EXPORT_SYMBOL_GPL(unlock_vm_area);
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/xen_guest.S linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/xen_guest.S
---- linux-2.6.18.8/arch/powerpc/platforms/xen/xen_guest.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/xen_guest.S 2008-02-15 16:21:53.000000000 -0800
-@@ -0,0 +1,27 @@
-+/*
-+ * 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; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * Copyright (C) IBM Corp. 2006
-+ *
-+ * Authors: Jimi Xenidis <jimix@watson.ibm.com>
-+ */
-+
-+ .section __xen_guest
-+ .ascii "GUEST_OS=linux"
-+ .ascii ",GUEST_VER=xen-3.0"
-+ .ascii ",XEN_VER=xen-3.0"
-+ .ascii ",VIRT_BASE=0xC000000000000000"
-+ .ascii ",LOADER=generic"
-+ .byte 0
-diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/xencomm.c linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/xencomm.c
---- linux-2.6.18.8/arch/powerpc/platforms/xen/xencomm.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/platforms/xen/xencomm.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/xencomm.c linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/xencomm.c
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/xencomm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/xencomm.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,54 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -39233,9 +39807,40 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/xencomm.c linux-2.6.18-xen-
+
+ return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
+}
-diff -rpuN linux-2.6.18.8/arch/powerpc/sysdev/mpic.c linux-2.6.18-xen-3.2.0/arch/powerpc/sysdev/mpic.c
---- linux-2.6.18.8/arch/powerpc/sysdev/mpic.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/sysdev/mpic.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/platforms/xen/xen_guest.S linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/xen_guest.S
+--- linux-2.6.18.8/arch/powerpc/platforms/xen/xen_guest.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/platforms/xen/xen_guest.S 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,27 @@
++/*
++ * 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; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Copyright (C) IBM Corp. 2006
++ *
++ * Authors: Jimi Xenidis <jimix@watson.ibm.com>
++ */
++
++ .section __xen_guest
++ .ascii "GUEST_OS=linux"
++ .ascii ",GUEST_VER=xen-3.0"
++ .ascii ",XEN_VER=xen-3.0"
++ .ascii ",VIRT_BASE=0xC000000000000000"
++ .ascii ",LOADER=generic"
++ .byte 0
+diff -rpuN linux-2.6.18.8/arch/powerpc/sysdev/mpic.c linux-2.6.18-xen-3.3.0/arch/powerpc/sysdev/mpic.c
+--- linux-2.6.18.8/arch/powerpc/sysdev/mpic.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/sysdev/mpic.c 2008-08-21 11:36:07.000000000 +0200
@@ -765,6 +765,9 @@ static int mpic_host_map(struct irq_host
else if (hw >= MPIC_VEC_IPI_0) {
WARN_ON(!(mpic->flags & MPIC_PRIMARY));
@@ -39264,9 +39869,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/sysdev/mpic.c linux-2.6.18-xen-3.2.0/arch
/* Initialize interrupt sources */
if (mpic->irq_count == 0)
mpic->irq_count = mpic->num_sources;
-diff -rpuN linux-2.6.18.8/arch/powerpc/xmon/xmon.c linux-2.6.18-xen-3.2.0/arch/powerpc/xmon/xmon.c
---- linux-2.6.18.8/arch/powerpc/xmon/xmon.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/powerpc/xmon/xmon.c 2008-02-15 16:21:53.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/powerpc/xmon/xmon.c linux-2.6.18-xen-3.3.0/arch/powerpc/xmon/xmon.c
+--- linux-2.6.18.8/arch/powerpc/xmon/xmon.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/powerpc/xmon/xmon.c 2008-08-21 11:36:07.000000000 +0200
@@ -752,6 +752,9 @@ cmds(struct pt_regs *excp)
cmd = inchar();
}
@@ -39277,238 +39882,9 @@ diff -rpuN linux-2.6.18.8/arch/powerpc/xmon/xmon.c linux-2.6.18-xen-3.2.0/arch/p
case 'm':
cmd = inchar();
switch (cmd) {
-diff -rpuN linux-2.6.18.8/arch/x86_64/Kconfig linux-2.6.18-xen-3.2.0/arch/x86_64/Kconfig
---- linux-2.6.18.8/arch/x86_64/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/Kconfig 2008-02-15 16:21:55.000000000 -0800
-@@ -135,6 +135,23 @@ config GENERIC_CPU
-
- endchoice
-
-+config X86_64_XEN
-+ bool "Enable Xen compatible kernel"
-+ select XEN
-+ select SWIOTLB
-+ help
-+ This option will compile a kernel compatible with Xen hypervisor
-+
-+config X86_NO_TSS
-+ bool
-+ depends on X86_64_XEN
-+ default y
-+
-+config X86_NO_IDT
-+ bool
-+ depends on X86_64_XEN
-+ default y
-+
- #
- # Define implied options from the CPU selection here
- #
-@@ -155,6 +172,7 @@ config X86_INTERNODE_CACHE_BYTES
-
- config X86_TSC
- bool
-+ depends on !X86_64_XEN
- default y
-
- config X86_GOOD_APIC
-@@ -197,7 +215,7 @@ config X86_CPUID
-
- config X86_HT
- bool
-- depends on SMP && !MK8
-+ depends on SMP && !MK8 && !X86_64_XEN
- default y
-
- config MATH_EMULATION
-@@ -211,14 +229,22 @@ config EISA
-
- config X86_IO_APIC
- bool
-+ depends !XEN_UNPRIVILEGED_GUEST
-+ default y
-+
-+config X86_XEN_GENAPIC
-+ bool
-+ depends on X86_64_XEN
- default y
-
- config X86_LOCAL_APIC
- bool
-+ depends !XEN_UNPRIVILEGED_GUEST
- default y
-
- config MTRR
- bool "MTRR (Memory Type Range Register) support"
-+ depends on !XEN_UNPRIVILEGED_GUEST
- ---help---
- On Intel P6 family processors (Pentium Pro, Pentium II and later)
- the Memory Type Range Registers (MTRRs) may be used to control
-@@ -259,7 +285,7 @@ config SMP
-
- config SCHED_SMT
- bool "SMT (Hyperthreading) scheduler support"
-- depends on SMP
-+ depends on SMP && !X86_64_XEN
- default n
- help
- SMT scheduler support improves the CPU scheduler's decision making
-@@ -269,7 +295,7 @@ config SCHED_SMT
-
- config SCHED_MC
- bool "Multi-core scheduler support"
-- depends on SMP
-+ depends on SMP && !X86_64_XEN
- default y
- help
- Multi-core scheduler support improves the CPU scheduler's decision
-@@ -280,7 +306,7 @@ source "kernel/Kconfig.preempt"
-
- config NUMA
- bool "Non Uniform Memory Access (NUMA) Support"
-- depends on SMP
-+ depends on SMP && !X86_64_XEN
- help
- Enable NUMA (Non Uniform Memory Access) support. The kernel
- will try to allocate memory used by a CPU on the local memory
-@@ -341,7 +367,7 @@ config ARCH_DISCONTIGMEM_DEFAULT
-
- config ARCH_SPARSEMEM_ENABLE
- def_bool y
-- depends on (NUMA || EXPERIMENTAL)
-+ depends on (NUMA || EXPERIMENTAL) && !X86_64_XEN
-
- config ARCH_MEMORY_PROBE
- def_bool y
-@@ -365,6 +391,7 @@ config NR_CPUS
- int "Maximum number of CPUs (2-256)"
- range 2 255
- depends on SMP
-+ default "16" if X86_64_XEN
- default "8"
- help
- This allows you to specify the maximum number of CPUs which this
-@@ -387,6 +414,7 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
-
- config HPET_TIMER
- bool
-+ depends on !X86_64_XEN
- default y
- help
- Use the IA-PC HPET (High Precision Event Timer) to manage
-@@ -407,7 +435,7 @@ config IOMMU
- default y
- select SWIOTLB
- select AGP
-- depends on PCI
-+ depends on PCI && !X86_64_XEN
- help
- Support for full DMA access of devices with 32bit memory access only
- on systems with more than 3GB. This is usually needed for USB,
-@@ -423,7 +451,7 @@ config CALGARY_IOMMU
- bool "IBM Calgary IOMMU support"
- default y
- select SWIOTLB
-- depends on PCI && EXPERIMENTAL
-+ depends on PCI && !X86_64_XEN && EXPERIMENTAL
- help
- Support for hardware IOMMUs in IBM's xSeries x366 and x460
- systems. Needed to run systems with more than 3GB of memory
-@@ -444,6 +472,7 @@ config SWIOTLB
-
- config X86_MCE
- bool "Machine check support" if EMBEDDED
-+ depends on !X86_64_XEN
- default y
- help
- Include a machine check error handler to report hardware errors.
-@@ -469,7 +498,7 @@ config X86_MCE_AMD
-
- config KEXEC
- bool "kexec system call (EXPERIMENTAL)"
-- depends on EXPERIMENTAL
-+ depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST
- help
- kexec is a system call that implements the ability to shutdown your
- current kernel, and to start another kernel. It is like a reboot
-@@ -564,8 +593,9 @@ config GENERIC_PENDING_IRQ
- default y
-
- menu "Power management options"
-+ depends on !XEN_UNPRIVILEGED_GUEST
-
--source kernel/power/Kconfig
-+source "kernel/power/Kconfig"
-
- source "drivers/acpi/Kconfig"
-
-@@ -588,6 +618,21 @@ config PCI_MMCONFIG
- bool "Support mmconfig PCI config space access"
- depends on PCI && ACPI
-
-+config XEN_PCIDEV_FRONTEND
-+ bool "Xen PCI Frontend"
-+ depends on PCI && X86_64_XEN
-+ default y
-+ help
-+ The PCI device frontend driver allows the kernel to import arbitrary
-+ PCI devices from a PCI backend to support PCI driver domains.
-+
-+config XEN_PCIDEV_FE_DEBUG
-+ bool "Xen PCI Frontend Debugging"
-+ depends on XEN_PCIDEV_FRONTEND
-+ default n
-+ help
-+ Enables some debug statements within the PCI Frontend.
-+
- source "drivers/pci/pcie/Kconfig"
-
- source "drivers/pci/Kconfig"
-@@ -658,4 +703,6 @@ source "security/Kconfig"
-
- source "crypto/Kconfig"
-
-+source "drivers/xen/Kconfig"
-+
- source "lib/Kconfig"
-diff -rpuN linux-2.6.18.8/arch/x86_64/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/Makefile
---- linux-2.6.18.8/arch/x86_64/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/Makefile 2008-02-15 16:21:55.000000000 -0800
-@@ -71,9 +71,22 @@ drivers-$(CONFIG_OPROFILE) += arch/x86_
-
- boot := arch/x86_64/boot
-
--PHONY += bzImage bzlilo install archmrproper \
-+PHONY += bzImage bzlilo vmlinuz install archmrproper \
- fdimage fdimage144 fdimage288 isoimage archclean
-
-+ifdef CONFIG_XEN
-+CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
-+ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS)
-+LDFLAGS_vmlinux := -e startup_64
-+#Default target when executing "make"
-+all: vmlinuz
-+
-+BOOTIMAGE := $(boot)/vmlinuz
-+KBUILD_IMAGE := $(BOOTIMAGE)
-+
-+vmlinuz: vmlinux
-+ $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
-+else
- #Default target when executing "make"
- all: bzImage
-
-@@ -91,6 +104,7 @@ bzdisk: vmlinux
-
- fdimage fdimage144 fdimage288 isoimage: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
-+endif
-
- install:
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
-diff -rpuN linux-2.6.18.8/arch/x86_64/boot/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/boot/Makefile
---- linux-2.6.18.8/arch/x86_64/boot/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/boot/Makefile 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/boot/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/boot/Makefile
+--- linux-2.6.18.8/arch/x86_64/boot/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/boot/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -26,7 +26,7 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
#RAMDISK := -DRAMDISK=512
@@ -39532,114 +39908,83 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/boot/Makefile linux-2.6.18-xen-3.2.0/arch/
+
install:
sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
-diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/Makefile
---- linux-2.6.18.8/arch/x86_64/ia32/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/Makefile 2008-02-15 16:21:55.000000000 -0800
-@@ -14,11 +14,14 @@ obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
- audit-class-$(CONFIG_AUDIT) := audit.o
- obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)
-
-+syscall32-types-y := sysenter syscall
-+syscall32-types-$(subst 1,$(CONFIG_XEN),$(shell expr $(CONFIG_XEN_COMPAT)0 '<' 0x0302000)) += int80
-+
- $(obj)/syscall32_syscall.o: \
-- $(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so)
-+ $(foreach F,$(syscall32-types-y),$(obj)/vsyscall-$F.so)
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/ia32_binfmt.c
+--- linux-2.6.18.8/arch/x86_64/ia32/ia32_binfmt.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/ia32_binfmt.c 2008-08-21 11:36:07.000000000 +0200
+@@ -65,55 +65,6 @@ typedef unsigned int elf_greg_t;
+ #define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t))
+ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
- # Teach kbuild about targets
--targets := $(foreach F,sysenter syscall,vsyscall-$F.o vsyscall-$F.so)
-+targets := $(foreach F,$(syscall32-types-y),vsyscall-$F.o vsyscall-$F.so)
-
- # The DSO images are built using a special linker script
- quiet_cmd_syscall = SYSCALL $@
-@@ -27,9 +30,10 @@ quiet_cmd_syscall = SYSCALL $@
- -Wl,-soname=linux-gate.so.1 -o $@ \
- -Wl,-T,$(filter-out FORCE,$^)
-
--$(obj)/vsyscall-sysenter.so $(obj)/vsyscall-syscall.so: \
-+$(foreach F,$(syscall32-types-y),$(obj)/vsyscall-$F.so): \
- $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
- $(call if_changed,syscall)
-
--AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32
--AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32
-+AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32 -Iarch/i386/kernel
-+AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32 -Iarch/i386/kernel
-+AFLAGS_vsyscall-int80.o = -m32 -Wa,-32 -Iarch/i386/kernel
-diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32_signal.c linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/ia32_signal.c
---- linux-2.6.18.8/arch/x86_64/ia32/ia32_signal.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/ia32_signal.c 2008-02-15 16:21:55.000000000 -0800
-@@ -113,25 +113,19 @@ int copy_siginfo_from_user32(siginfo_t *
- }
-
- asmlinkage long
--sys32_sigsuspend(int history0, int history1, old_sigset_t mask,
-- struct pt_regs *regs)
-+sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
- {
-- sigset_t saveset;
+-/*
+- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+- * extra segments containing the vsyscall DSO contents. Dumping its
+- * contents makes post-mortem fully interpretable later without matching up
+- * the same kernel and hardware config to see what PC values meant.
+- * Dumping its extra ELF program headers includes all the other information
+- * a debugger needs to easily find how the vsyscall DSO was being used.
+- */
+-#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \
+- (VSYSCALL32_EHDR->e_phnum) : 0)
+-#define ELF_CORE_WRITE_EXTRA_PHDRS \
+-do { \
+- if (find_vma(current->mm, VSYSCALL32_BASE)) { \
+- const struct elf32_phdr *const vsyscall_phdrs = \
+- (const struct elf32_phdr *) (VSYSCALL32_BASE \
+- + VSYSCALL32_EHDR->e_phoff);\
+- int i; \
+- Elf32_Off ofs = 0; \
+- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
+- struct elf32_phdr phdr = vsyscall_phdrs[i]; \
+- if (phdr.p_type == PT_LOAD) { \
+- BUG_ON(ofs != 0); \
+- ofs = phdr.p_offset = offset; \
+- phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
+- phdr.p_filesz = phdr.p_memsz; \
+- offset += phdr.p_filesz; \
+- } \
+- else \
+- phdr.p_offset += ofs; \
+- phdr.p_paddr = 0; /* match other core phdrs */ \
+- DUMP_WRITE(&phdr, sizeof(phdr)); \
+- } \
+- } \
+-} while (0)
+-#define ELF_CORE_WRITE_EXTRA_DATA \
+-do { \
+- if (find_vma(current->mm, VSYSCALL32_BASE)) { \
+- const struct elf32_phdr *const vsyscall_phdrs = \
+- (const struct elf32_phdr *) (VSYSCALL32_BASE \
+- + VSYSCALL32_EHDR->e_phoff); \
+- int i; \
+- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
+- if (vsyscall_phdrs[i].p_type == PT_LOAD) \
+- DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\
+- PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+- } \
+- } \
+-} while (0)
-
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
-- saveset = current->blocked;
-+ current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
-- regs->rax = -EINTR;
-- while (1) {
-- current->state = TASK_INTERRUPTIBLE;
-- schedule();
-- if (do_signal(regs, &saveset))
-- return -EINTR;
-- }
-+ current->state = TASK_INTERRUPTIBLE;
-+ schedule();
-+ set_thread_flag(TIF_RESTORE_SIGMASK);
-+ return -ERESTARTNOHAND;
- }
-
- asmlinkage long
-@@ -508,11 +502,11 @@ int ia32_setup_frame(int sig, struct k_s
- current->comm, current->pid, frame, regs->rip, frame->pretcode);
- #endif
-
-- return 1;
-+ return 0;
-
- give_sigsegv:
- force_sigsegv(sig, current);
-- return 0;
-+ return -EFAULT;
- }
-
- int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-@@ -595,7 +589,7 @@ int ia32_setup_rt_frame(int sig, struct
- regs->ss = __USER32_DS;
-
- set_fs(USER_DS);
-- regs->eflags &= ~TF_MASK;
-+ regs->eflags &= ~TF_MASK;
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-
-@@ -604,9 +598,9 @@ int ia32_setup_rt_frame(int sig, struct
- current->comm, current->pid, frame, regs->rip, frame->pretcode);
- #endif
-
-- return 1;
-+ return 0;
-
- give_sigsegv:
- force_sigsegv(sig, current);
-- return 0;
-+ return -EFAULT;
- }
-diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32entry-xen.S linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/ia32entry-xen.S
---- linux-2.6.18.8/arch/x86_64/ia32/ia32entry-xen.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/ia32entry-xen.S 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,668 @@
+ struct elf_siginfo
+ {
+ int si_signo; /* signal number */
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32entry.S linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/ia32entry.S
+--- linux-2.6.18.8/arch/x86_64/ia32/ia32entry.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/ia32entry.S 2008-08-21 11:36:07.000000000 +0200
+@@ -703,8 +703,8 @@ ia32_sys_call_table:
+ .quad sys_readlinkat /* 305 */
+ .quad sys_fchmodat
+ .quad sys_faccessat
+- .quad quiet_ni_syscall /* pselect6 for now */
+- .quad quiet_ni_syscall /* ppoll for now */
++ .quad compat_sys_pselect6
++ .quad compat_sys_ppoll
+ .quad sys_unshare /* 310 */
+ .quad compat_sys_set_robust_list
+ .quad compat_sys_get_robust_list
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32entry-xen.S linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/ia32entry-xen.S
+--- linux-2.6.18.8/arch/x86_64/ia32/ia32entry-xen.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/ia32entry-xen.S 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,666 @@
+/*
+ * Compatibility mode system call entry point for x86-64.
+ *
@@ -39692,8 +40037,6 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32entry-xen.S linux-2.6.18-xen-3.2.
+ movl \offset+72(%rsp),%eax
+ .endm
+
-+#include "../kernel/xen_entry.S"
-+
+ .macro CFI_STARTPROC32 simple
+ CFI_STARTPROC \simple
+ CFI_UNDEFINED r8
@@ -40308,23 +40651,162 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32entry-xen.S linux-2.6.18-xen-3.2.
+ .quad compat_sys_vmsplice
+ .quad compat_sys_move_pages
+ia32_syscall_end:
-diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32entry.S linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/ia32entry.S
---- linux-2.6.18.8/arch/x86_64/ia32/ia32entry.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/ia32entry.S 2008-02-15 16:21:55.000000000 -0800
-@@ -703,8 +703,8 @@ ia32_sys_call_table:
- .quad sys_readlinkat /* 305 */
- .quad sys_fchmodat
- .quad sys_faccessat
-- .quad quiet_ni_syscall /* pselect6 for now */
-- .quad quiet_ni_syscall /* ppoll for now */
-+ .quad compat_sys_pselect6
-+ .quad compat_sys_ppoll
- .quad sys_unshare /* 310 */
- .quad compat_sys_set_robust_list
- .quad compat_sys_get_robust_list
-diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/syscall32-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/syscall32-xen.c
---- linux-2.6.18.8/arch/x86_64/ia32/syscall32-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/syscall32-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/ia32_signal.c linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/ia32_signal.c
+--- linux-2.6.18.8/arch/x86_64/ia32/ia32_signal.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/ia32_signal.c 2008-08-21 11:36:07.000000000 +0200
+@@ -113,25 +113,19 @@ int copy_siginfo_from_user32(siginfo_t *
+ }
+
+ asmlinkage long
+-sys32_sigsuspend(int history0, int history1, old_sigset_t mask,
+- struct pt_regs *regs)
++sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
+ {
+- sigset_t saveset;
+-
+ mask &= _BLOCKABLE;
+ spin_lock_irq(&current->sighand->siglock);
+- saveset = current->blocked;
++ current->saved_sigmask = current->blocked;
+ siginitset(&current->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+- regs->rax = -EINTR;
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal(regs, &saveset))
+- return -EINTR;
+- }
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ set_thread_flag(TIF_RESTORE_SIGMASK);
++ return -ERESTARTNOHAND;
+ }
+
+ asmlinkage long
+@@ -508,11 +502,11 @@ int ia32_setup_frame(int sig, struct k_s
+ current->comm, current->pid, frame, regs->rip, frame->pretcode);
+ #endif
+
+- return 1;
++ return 0;
+
+ give_sigsegv:
+ force_sigsegv(sig, current);
+- return 0;
++ return -EFAULT;
+ }
+
+ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+@@ -595,7 +589,7 @@ int ia32_setup_rt_frame(int sig, struct
+ regs->ss = __USER32_DS;
+
+ set_fs(USER_DS);
+- regs->eflags &= ~TF_MASK;
++ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+@@ -604,9 +598,9 @@ int ia32_setup_rt_frame(int sig, struct
+ current->comm, current->pid, frame, regs->rip, frame->pretcode);
+ #endif
+
+- return 1;
++ return 0;
+
+ give_sigsegv:
+ force_sigsegv(sig, current);
+- return 0;
++ return -EFAULT;
+ }
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/Makefile
+--- linux-2.6.18.8/arch/x86_64/ia32/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -14,11 +14,14 @@ obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
+ audit-class-$(CONFIG_AUDIT) := audit.o
+ obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)
+
++syscall32-types-y := sysenter syscall
++syscall32-types-$(subst 1,$(CONFIG_XEN),$(shell expr $(CONFIG_XEN_COMPAT)0 '<' 0x0302000)) += int80
++
+ $(obj)/syscall32_syscall.o: \
+- $(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so)
++ $(foreach F,$(syscall32-types-y),$(obj)/vsyscall-$F.so)
+
+ # Teach kbuild about targets
+-targets := $(foreach F,sysenter syscall,vsyscall-$F.o vsyscall-$F.so)
++targets := $(foreach F,$(syscall32-types-y),vsyscall-$F.o vsyscall-$F.so)
+
+ # The DSO images are built using a special linker script
+ quiet_cmd_syscall = SYSCALL $@
+@@ -27,9 +30,10 @@ quiet_cmd_syscall = SYSCALL $@
+ -Wl,-soname=linux-gate.so.1 -o $@ \
+ -Wl,-T,$(filter-out FORCE,$^)
+
+-$(obj)/vsyscall-sysenter.so $(obj)/vsyscall-syscall.so: \
++$(foreach F,$(syscall32-types-y),$(obj)/vsyscall-$F.so): \
+ $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+ $(call if_changed,syscall)
+
+-AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32
+-AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32
++AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32 -Iarch/i386/kernel
++AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32 -Iarch/i386/kernel
++AFLAGS_vsyscall-int80.o = -m32 -Wa,-32 -Iarch/i386/kernel
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/syscall32.c linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/syscall32.c
+--- linux-2.6.18.8/arch/x86_64/ia32/syscall32.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/syscall32.c 2008-08-21 11:36:07.000000000 +0200
+@@ -59,6 +59,13 @@ int syscall32_setup_pages(struct linux_b
+ vma->vm_end = VSYSCALL32_END;
+ /* MAYWRITE to allow gdb to COW and set breakpoints */
+ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
++ /*
++ * Make sure the vDSO gets into every core dump.
++ * Dumping its contents makes post-mortem fully interpretable later
++ * without matching up the same kernel and hardware config to see
++ * what PC values meant.
++ */
++ vma->vm_flags |= VM_ALWAYSDUMP;
+ vma->vm_flags |= mm->def_flags;
+ vma->vm_page_prot = protection_map[vma->vm_flags & 7];
+ vma->vm_ops = &syscall32_vm_ops;
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/syscall32_syscall-xen.S linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/syscall32_syscall-xen.S
+--- linux-2.6.18.8/arch/x86_64/ia32/syscall32_syscall-xen.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/syscall32_syscall-xen.S 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,28 @@
++/* 32bit VDSOs mapped into user space. */
++
++ .section ".init.data","aw"
++
++#if CONFIG_XEN_COMPAT < 0x030200
++
++ .globl syscall32_int80
++ .globl syscall32_int80_end
++
++syscall32_int80:
++ .incbin "arch/x86_64/ia32/vsyscall-int80.so"
++syscall32_int80_end:
++
++#endif
++
++ .globl syscall32_syscall
++ .globl syscall32_syscall_end
++
++syscall32_syscall:
++ .incbin "arch/x86_64/ia32/vsyscall-syscall.so"
++syscall32_syscall_end:
++
++ .globl syscall32_sysenter
++ .globl syscall32_sysenter_end
++
++syscall32_sysenter:
++ .incbin "arch/x86_64/ia32/vsyscall-sysenter.so"
++syscall32_sysenter_end:
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/syscall32-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/syscall32-xen.c
+--- linux-2.6.18.8/arch/x86_64/ia32/syscall32-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/syscall32-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,137 @@
+/* Copyright 2002,2003 Andi Kleen, SuSE Labs */
+
@@ -40463,41 +40945,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/syscall32-xen.c linux-2.6.18-xen-3.2.
+ if (use_sysenter < 0)
+ use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL);
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/syscall32_syscall-xen.S linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/syscall32_syscall-xen.S
---- linux-2.6.18.8/arch/x86_64/ia32/syscall32_syscall-xen.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/syscall32_syscall-xen.S 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,28 @@
-+/* 32bit VDSOs mapped into user space. */
-+
-+ .section ".init.data","aw"
-+
-+#if CONFIG_XEN_COMPAT < 0x030200
-+
-+ .globl syscall32_int80
-+ .globl syscall32_int80_end
-+
-+syscall32_int80:
-+ .incbin "arch/x86_64/ia32/vsyscall-int80.so"
-+syscall32_int80_end:
-+
-+#endif
-+
-+ .globl syscall32_syscall
-+ .globl syscall32_syscall_end
-+
-+syscall32_syscall:
-+ .incbin "arch/x86_64/ia32/vsyscall-syscall.so"
-+syscall32_syscall_end:
-+
-+ .globl syscall32_sysenter
-+ .globl syscall32_sysenter_end
-+
-+syscall32_sysenter:
-+ .incbin "arch/x86_64/ia32/vsyscall-sysenter.so"
-+syscall32_sysenter_end:
-diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/vsyscall-int80.S linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/vsyscall-int80.S
---- linux-2.6.18.8/arch/x86_64/ia32/vsyscall-int80.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/vsyscall-int80.S 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/vsyscall-int80.S linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/vsyscall-int80.S
+--- linux-2.6.18.8/arch/x86_64/ia32/vsyscall-int80.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/vsyscall-int80.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,58 @@
+/*
+ * Code for the vsyscall page. This version uses the old int $0x80 method.
@@ -40557,9 +41007,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/vsyscall-int80.S linux-2.6.18-xen-3.2
+ */
+#define SYSCALL_ENTER_KERNEL int $0x80
+#include "vsyscall-sigreturn.S"
-diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/vsyscall-sigreturn.S linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/vsyscall-sigreturn.S
---- linux-2.6.18.8/arch/x86_64/ia32/vsyscall-sigreturn.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/ia32/vsyscall-sigreturn.S 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/vsyscall-sigreturn.S linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/vsyscall-sigreturn.S
+--- linux-2.6.18.8/arch/x86_64/ia32/vsyscall-sigreturn.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/ia32/vsyscall-sigreturn.S 2008-08-21 11:36:07.000000000 +0200
@@ -139,5 +139,5 @@ __kernel_rt_sigreturn:
.align 4
.LENDFDE3:
@@ -40567,48 +41017,219 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/ia32/vsyscall-sigreturn.S linux-2.6.18-xen
-#include "../../i386/kernel/vsyscall-note.S"
+#include <vsyscall-note.S>
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/Makefile
---- linux-2.6.18.8/arch/x86_64/kernel/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/Makefile 2008-02-15 16:21:55.000000000 -0800
-@@ -21,11 +21,13 @@ obj-$(CONFIG_MICROCODE) += microcode.o
- obj-$(CONFIG_X86_CPUID) += cpuid.o
- obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
- obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
-+obj-$(CONFIG_X86_XEN_GENAPIC) += genapic.o genapic_xen.o
- obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \
- genapic.o genapic_cluster.o genapic_flat.o
- obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
- obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
--obj-$(CONFIG_PM) += suspend.o
-+obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
-+obj-$(CONFIG_ACPI_SLEEP) += suspend.o
- obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o
- obj-$(CONFIG_CPU_FREQ) += cpufreq/
- obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-@@ -55,3 +57,8 @@ i8237-y += ../../i386/kernel/i8237.o
- msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
- alternative-y += ../../i386/kernel/alternative.o
+diff -rpuN linux-2.6.18.8/arch/x86_64/Kconfig linux-2.6.18-xen-3.3.0/arch/x86_64/Kconfig
+--- linux-2.6.18.8/arch/x86_64/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -135,6 +135,23 @@ config GENERIC_CPU
-+time-$(CONFIG_XEN) += ../../i386/kernel/time.o
-+pci-dma-$(CONFIG_XEN) += ../../i386/kernel/pci-dma.o
+ endchoice
+
++config X86_64_XEN
++ bool "Enable Xen compatible kernel"
++ select XEN
++ select SWIOTLB
++ help
++ This option will compile a kernel compatible with Xen hypervisor
+
-+disabled-obj-$(CONFIG_XEN) := i8259.o reboot.o smpboot.o trampoline.o
-+%/head.o %/head.s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/acpi/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/acpi/Makefile
---- linux-2.6.18.8/arch/x86_64/kernel/acpi/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/acpi/Makefile 2008-02-15 16:21:55.000000000 -0800
-@@ -5,5 +5,7 @@ obj-$(CONFIG_ACPI_SLEEP) += sleep.o wake
++config X86_NO_TSS
++ bool
++ depends on X86_64_XEN
++ default y
++
++config X86_NO_IDT
++ bool
++ depends on X86_64_XEN
++ default y
++
+ #
+ # Define implied options from the CPU selection here
+ #
+@@ -155,6 +172,7 @@ config X86_INTERNODE_CACHE_BYTES
+
+ config X86_TSC
+ bool
++ depends on !X86_64_XEN
+ default y
+
+ config X86_GOOD_APIC
+@@ -197,7 +215,7 @@ config X86_CPUID
+
+ config X86_HT
+ bool
+- depends on SMP && !MK8
++ depends on SMP && !MK8 && !X86_64_XEN
+ default y
+
+ config MATH_EMULATION
+@@ -211,14 +229,22 @@ config EISA
+
+ config X86_IO_APIC
+ bool
++ depends !XEN_UNPRIVILEGED_GUEST
++ default y
++
++config X86_XEN_GENAPIC
++ bool
++ depends on X86_64_XEN
+ default y
+
+ config X86_LOCAL_APIC
+ bool
++ depends !XEN_UNPRIVILEGED_GUEST
+ default y
+
+ config MTRR
+ bool "MTRR (Memory Type Range Register) support"
++ depends on !XEN_UNPRIVILEGED_GUEST
+ ---help---
+ On Intel P6 family processors (Pentium Pro, Pentium II and later)
+ the Memory Type Range Registers (MTRRs) may be used to control
+@@ -259,7 +285,7 @@ config SMP
+
+ config SCHED_SMT
+ bool "SMT (Hyperthreading) scheduler support"
+- depends on SMP
++ depends on SMP && !X86_64_XEN
+ default n
+ help
+ SMT scheduler support improves the CPU scheduler's decision making
+@@ -269,7 +295,7 @@ config SCHED_SMT
+
+ config SCHED_MC
+ bool "Multi-core scheduler support"
+- depends on SMP
++ depends on SMP && !X86_64_XEN
+ default y
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+@@ -280,7 +306,7 @@ source "kernel/Kconfig.preempt"
+
+ config NUMA
+ bool "Non Uniform Memory Access (NUMA) Support"
+- depends on SMP
++ depends on SMP && !X86_64_XEN
+ help
+ Enable NUMA (Non Uniform Memory Access) support. The kernel
+ will try to allocate memory used by a CPU on the local memory
+@@ -341,7 +367,7 @@ config ARCH_DISCONTIGMEM_DEFAULT
+
+ config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+- depends on (NUMA || EXPERIMENTAL)
++ depends on (NUMA || EXPERIMENTAL) && !X86_64_XEN
+
+ config ARCH_MEMORY_PROBE
+ def_bool y
+@@ -365,6 +391,7 @@ config NR_CPUS
+ int "Maximum number of CPUs (2-256)"
+ range 2 255
+ depends on SMP
++ default "16" if X86_64_XEN
+ default "8"
+ help
+ This allows you to specify the maximum number of CPUs which this
+@@ -387,6 +414,7 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
+
+ config HPET_TIMER
+ bool
++ depends on !X86_64_XEN
+ default y
+ help
+ Use the IA-PC HPET (High Precision Event Timer) to manage
+@@ -407,7 +435,7 @@ config IOMMU
+ default y
+ select SWIOTLB
+ select AGP
+- depends on PCI
++ depends on PCI && !X86_64_XEN
+ help
+ Support for full DMA access of devices with 32bit memory access only
+ on systems with more than 3GB. This is usually needed for USB,
+@@ -423,7 +451,7 @@ config CALGARY_IOMMU
+ bool "IBM Calgary IOMMU support"
+ default y
+ select SWIOTLB
+- depends on PCI && EXPERIMENTAL
++ depends on PCI && !X86_64_XEN && EXPERIMENTAL
+ help
+ Support for hardware IOMMUs in IBM's xSeries x366 and x460
+ systems. Needed to run systems with more than 3GB of memory
+@@ -444,6 +472,7 @@ config SWIOTLB
+
+ config X86_MCE
+ bool "Machine check support" if EMBEDDED
++ depends on !X86_64_XEN
+ default y
+ help
+ Include a machine check error handler to report hardware errors.
+@@ -469,7 +498,7 @@ config X86_MCE_AMD
+
+ config KEXEC
+ bool "kexec system call (EXPERIMENTAL)"
+- depends on EXPERIMENTAL
++ depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+@@ -564,8 +593,9 @@ config GENERIC_PENDING_IRQ
+ default y
+
+ menu "Power management options"
++ depends on !XEN_UNPRIVILEGED_GUEST
+
+-source kernel/power/Kconfig
++source "kernel/power/Kconfig"
+
+ source "drivers/acpi/Kconfig"
+
+@@ -588,6 +618,22 @@ config PCI_MMCONFIG
+ bool "Support mmconfig PCI config space access"
+ depends on PCI && ACPI
+
++config XEN_PCIDEV_FRONTEND
++ bool "Xen PCI Frontend"
++ depends on PCI && X86_64_XEN
++ select HOTPLUG
++ default y
++ help
++ The PCI device frontend driver allows the kernel to import arbitrary
++ PCI devices from a PCI backend to support PCI driver domains.
++
++config XEN_PCIDEV_FE_DEBUG
++ bool "Xen PCI Frontend Debugging"
++ depends on XEN_PCIDEV_FRONTEND
++ default n
++ help
++ Enables some debug statements within the PCI Frontend.
++
+ source "drivers/pci/pcie/Kconfig"
+
+ source "drivers/pci/Kconfig"
+@@ -658,4 +704,6 @@ source "security/Kconfig"
+
+ source "crypto/Kconfig"
+
++source "drivers/xen/Kconfig"
++
+ source "lib/Kconfig"
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/acpi/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/acpi/Makefile
+--- linux-2.6.18.8/arch/x86_64/kernel/acpi/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/acpi/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -5,5 +5,10 @@ obj-$(CONFIG_ACPI_SLEEP) += sleep.o wake
ifneq ($(CONFIG_ACPI_PROCESSOR),)
obj-y += processor.o
processor-y := ../../../i386/kernel/acpi/processor.o ../../../i386/kernel/acpi/cstate.o
+processor-$(CONFIG_XEN) := ../../../i386/kernel/acpi/processor.o
++ifneq ($(CONFIG_PROCESSOR_EXTERNAL_CONTROL),)
++processor-$(CONFIG_XEN) += ../../../i386/kernel/acpi/processor_extcntl_xen.o
++endif
endif
+disabled-obj-$(CONFIG_XEN) := wakeup.o
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/acpi/sleep-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/acpi/sleep-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/acpi/sleep-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/acpi/sleep-xen.c 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,167 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/acpi/sleep-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/acpi/sleep-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/acpi/sleep-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/acpi/sleep-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,146 @@
+/*
+ * acpi.c - Architecture-Specific Low-Level ACPI Support
+ *
@@ -40748,27 +41369,6 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/acpi/sleep-xen.c linux-2.6.18-xen-3
+}
+
+__setup("acpi_sleep=", acpi_sleep_setup);
-+
-+#else /* CONFIG_ACPI_PV_SLEEP */
-+#include <asm/hypervisor.h>
-+#include <xen/interface/platform.h>
-+int acpi_notify_hypervisor_state(u8 sleep_state,
-+ u32 pm1a_cnt, u32 pm1b_cnt)
-+{
-+ struct xen_platform_op op = {
-+ .cmd = XENPF_enter_acpi_sleep,
-+ .interface_version = XENPF_INTERFACE_VERSION,
-+ .u = {
-+ .enter_acpi_sleep = {
-+ .pm1a_cnt_val = (u16)pm1a_cnt,
-+ .pm1b_cnt_val = (u16)pm1b_cnt,
-+ .sleep_state = sleep_state,
-+ },
-+ },
-+ };
-+
-+ return HYPERVISOR_platform_op(&op);
-+}
+#endif /* CONFIG_ACPI_PV_SLEEP */
+
+#endif /*CONFIG_ACPI_SLEEP */
@@ -40776,9 +41376,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/acpi/sleep-xen.c linux-2.6.18-xen-3
+void acpi_pci_link_exit(void)
+{
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/apic-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/apic-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/apic-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/apic-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/apic-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/apic-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/apic-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/apic-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,197 @@
+/*
+ * Local APIC handling, local APIC timers
@@ -40977,9 +41577,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/apic-xen.c linux-2.6.18-xen-3.2.0/a
+
+ return 1;
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/asm-offsets.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/asm-offsets.c
---- linux-2.6.18.8/arch/x86_64/kernel/asm-offsets.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/asm-offsets.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/asm-offsets.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/asm-offsets.c
+--- linux-2.6.18.8/arch/x86_64/kernel/asm-offsets.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/asm-offsets.c 2008-08-21 11:36:07.000000000 +0200
@@ -67,8 +67,10 @@ int main(void)
DEFINE(pbe_address, offsetof(struct pbe, address));
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
@@ -40991,9 +41591,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/asm-offsets.c linux-2.6.18-xen-3.2.
BLANK();
DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
return 0;
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/crash.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/crash.c
---- linux-2.6.18.8/arch/x86_64/kernel/crash.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/crash.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/crash.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/crash.c
+--- linux-2.6.18.8/arch/x86_64/kernel/crash.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/crash.c 2008-08-21 11:36:07.000000000 +0200
@@ -92,6 +92,7 @@ static void crash_save_self(struct pt_re
crash_save_this_cpu(regs, cpu);
}
@@ -41027,10 +41627,30 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/crash.c linux-2.6.18-xen-3.2.0/arch
+#endif /* CONFIG_XEN */
crash_save_self(regs);
}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/e820-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/e820-xen.c 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,783 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/e820.c
+--- linux-2.6.18.8/arch/x86_64/kernel/e820.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/e820.c 2008-08-21 11:36:07.000000000 +0200
+@@ -93,7 +93,7 @@ static inline int bad_addr(unsigned long
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+ */
+-int __meminit
++int
+ e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
+ {
+ int i;
+@@ -107,6 +107,7 @@ e820_any_mapped(unsigned long start, uns
+ }
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(e820_any_mapped);
+
+ /*
+ * This function checks if the entire range <start,end> is mapped with type.
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/e820-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/e820-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,798 @@
+/*
+ * Handle the memory map.
+ * The functions here do the job until bootmem takes over.
@@ -41078,6 +41698,10 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c linux-2.6.18-xen-3.2.0/a
+
+extern struct resource code_resource, data_resource;
+
++#ifdef CONFIG_XEN
++extern struct e820map machine_e820;
++#endif
++
+/* Check for some hardcoded bad areas that early boot is not allowed to touch */
+static inline int bad_addr(unsigned long *addrp, unsigned long size)
+{
@@ -41142,8 +41766,6 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c linux-2.6.18-xen-3.2.0/a
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+#else
-+ extern struct e820map machine_e820;
-+
+ if (!is_initial_xendomain())
+ return 0;
+ for (i = 0; i < machine_e820.nr_map; i++) {
@@ -41174,8 +41796,6 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c linux-2.6.18-xen-3.2.0/a
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+#else
-+ extern struct e820map machine_e820;
-+
+ if (!is_initial_xendomain())
+ return 0;
+ for (i = 0; i < machine_e820.nr_map; i++) {
@@ -41637,6 +42257,21 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c linux-2.6.18-xen-3.2.0/a
+
+ add_memory_region(start, size, type);
+ } while (biosmap++,--nr_map);
++
++#ifdef CONFIG_XEN
++ if (is_initial_xendomain()) {
++ struct xen_memory_map memmap;
++
++ memmap.nr_entries = E820MAX;
++ set_xen_guest_handle(memmap.buffer, machine_e820.map);
++
++ if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap))
++ BUG();
++ machine_e820.nr_map = memmap.nr_entries;
++ } else
++ machine_e820 = e820;
++#endif
++
+ return 0;
+}
+
@@ -41814,29 +42449,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820-xen.c linux-2.6.18-xen-3.2.0/a
+ printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
+ pci_mem_start, gapstart, gapsize);
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/e820.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/e820.c
---- linux-2.6.18.8/arch/x86_64/kernel/e820.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/e820.c 2008-02-15 16:21:55.000000000 -0800
-@@ -93,7 +93,7 @@ static inline int bad_addr(unsigned long
- * This function checks if any part of the range <start,end> is mapped
- * with type.
- */
--int __meminit
-+int
- e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
- {
- int i;
-@@ -107,6 +107,7 @@ e820_any_mapped(unsigned long start, uns
- }
- return 0;
- }
-+EXPORT_SYMBOL_GPL(e820_any_mapped);
-
- /*
- * This function checks if the entire range <start,end> is mapped with type.
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/early_printk-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/early_printk-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/early_printk-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/early_printk-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/early_printk-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/early_printk-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/early_printk-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/early_printk-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,302 @@
+#include <linux/console.h>
+#include <linux/kernel.h>
@@ -42140,9 +42755,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/early_printk-xen.c linux-2.6.18-xen
+}
+
+__setup("earlyprintk=", setup_early_printk);
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/entry-xen.S linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/entry-xen.S
---- linux-2.6.18.8/arch/x86_64/kernel/entry-xen.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/entry-xen.S 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/entry-xen.S linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/entry-xen.S
+--- linux-2.6.18.8/arch/x86_64/kernel/entry-xen.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/entry-xen.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1322 @@
+/*
+ * linux/arch/x86_64/entry.S
@@ -42330,7 +42945,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/entry-xen.S linux-2.6.18-xen-3.2.0/
+ CFI_ADJUST_CFA_OFFSET -4
+ call schedule_tail
+ GET_THREAD_INFO(%rcx)
-+ testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
++ testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
+ jnz rff_trace
+rff_action:
+ RESTORE_REST
@@ -42480,10 +43095,10 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/entry-xen.S linux-2.6.18-xen-3.2.0/
+ LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
+ RESTORE_REST
+ cmpq $__NR_syscall_max,%rax
-+ ja 1f
++ ja int_ret_from_sys_call
+ movq %r10,%rcx /* fixup for C */
+ call *sys_call_table(,%rax,8)
-+1: movq %rax,RAX-ARGOFFSET(%rsp)
++ movq %rax,RAX-ARGOFFSET(%rsp)
+ /* Use IRET because user could have changed frame */
+ jmp int_ret_from_sys_call
+ CFI_ENDPROC
@@ -43466,9 +44081,174 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/entry-xen.S linux-2.6.18-xen-3.2.0/
+ CFI_ENDPROC
+ENDPROC(arch_unwind_init_running)
+#endif
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/genapic-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/genapic-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/genapic-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/genapic-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/genapic_xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/genapic_xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/genapic_xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/genapic_xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,161 @@
++/*
++ * Copyright 2004 James Cleverdon, IBM.
++ * Subject to the GNU Public License, v.2
++ *
++ * Xen APIC subarch code. Maximum 8 CPUs, logical delivery.
++ *
++ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
++ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
++ * James Cleverdon.
++ *
++ * Hacked to pieces for Xen by Chris Wright.
++ */
++#include <linux/threads.h>
++#include <linux/cpumask.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/init.h>
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
++#include <asm/smp.h>
++#include <asm/ipi.h>
++#else
++#include <asm/apic.h>
++#include <asm/apicdef.h>
++#include <asm/genapic.h>
++#endif
++#include <xen/evtchn.h>
++
++DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
++
++static inline void __send_IPI_one(unsigned int cpu, int vector)
++{
++ int irq = per_cpu(ipi_to_irq, cpu)[vector];
++ BUG_ON(irq < 0);
++ notify_remote_via_irq(irq);
++}
++
++void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
++{
++ int cpu;
++
++ switch (shortcut) {
++ case APIC_DEST_SELF:
++ __send_IPI_one(smp_processor_id(), vector);
++ break;
++ case APIC_DEST_ALLBUT:
++ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
++ if (cpu == smp_processor_id())
++ continue;
++ if (cpu_isset(cpu, cpu_online_map)) {
++ __send_IPI_one(cpu, vector);
++ }
++ }
++ break;
++ case APIC_DEST_ALLINC:
++ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
++ if (cpu_isset(cpu, cpu_online_map)) {
++ __send_IPI_one(cpu, vector);
++ }
++ }
++ break;
++ default:
++ printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
++ vector);
++ break;
++ }
++}
++
++static cpumask_t xen_target_cpus(void)
++{
++ return cpu_online_map;
++}
++
++/*
++ * Set up the logical destination ID.
++ * Do nothing, not called now.
++ */
++static void xen_init_apic_ldr(void)
++{
++ Dprintk("%s\n", __FUNCTION__);
++ return;
++}
++
++static void xen_send_IPI_allbutself(int vector)
++{
++ /*
++ * if there are no other CPUs in the system then
++ * we get an APIC send error if we try to broadcast.
++ * thus we have to avoid sending IPIs in this case.
++ */
++ Dprintk("%s\n", __FUNCTION__);
++ if (num_online_cpus() > 1)
++ xen_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
++}
++
++static void xen_send_IPI_all(int vector)
++{
++ Dprintk("%s\n", __FUNCTION__);
++ xen_send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
++}
++
++static void xen_send_IPI_mask(cpumask_t cpumask, int vector)
++{
++ unsigned long mask = cpus_addr(cpumask)[0];
++ unsigned int cpu;
++ unsigned long flags;
++
++ Dprintk("%s\n", __FUNCTION__);
++ local_irq_save(flags);
++ WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
++
++ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
++ if (cpu_isset(cpu, cpumask)) {
++ __send_IPI_one(cpu, vector);
++ }
++ }
++ local_irq_restore(flags);
++}
++
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
++static int xen_apic_id_registered(void)
++{
++ /* better be set */
++ Dprintk("%s\n", __FUNCTION__);
++ return physid_isset(smp_processor_id(), phys_cpu_present_map);
++}
++#endif
++
++static unsigned int xen_cpu_mask_to_apicid(cpumask_t cpumask)
++{
++ Dprintk("%s\n", __FUNCTION__);
++ return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
++}
++
++static unsigned int phys_pkg_id(int index_msb)
++{
++ u32 ebx;
++
++ Dprintk("%s\n", __FUNCTION__);
++ ebx = cpuid_ebx(1);
++ return ((ebx >> 24) & 0xFF) >> index_msb;
++}
++
++struct genapic apic_xen = {
++ .name = "xen",
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
++ .int_delivery_mode = dest_LowestPrio,
++#endif
++ .int_dest_mode = (APIC_DEST_LOGICAL != 0),
++ .int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
++ .target_cpus = xen_target_cpus,
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
++ .apic_id_registered = xen_apic_id_registered,
++#endif
++ .init_apic_ldr = xen_init_apic_ldr,
++ .send_IPI_all = xen_send_IPI_all,
++ .send_IPI_allbutself = xen_send_IPI_allbutself,
++ .send_IPI_mask = xen_send_IPI_mask,
++ .cpu_mask_to_apicid = xen_cpu_mask_to_apicid,
++ .phys_pkg_id = phys_pkg_id,
++};
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/genapic-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/genapic-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/genapic-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/genapic-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2004 James Cleverdon, IBM.
@@ -43613,174 +44393,175 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/genapic-xen.c linux-2.6.18-xen-3.2.
+ xen_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
+#endif
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/genapic_xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/genapic_xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/genapic_xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/genapic_xen.c 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,161 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/head64-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/head64-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/head64-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/head64-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,162 @@
+/*
-+ * Copyright 2004 James Cleverdon, IBM.
-+ * Subject to the GNU Public License, v.2
-+ *
-+ * Xen APIC subarch code. Maximum 8 CPUs, logical delivery.
++ * linux/arch/x86_64/kernel/head64.c -- prepare to run common code
+ *
-+ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
-+ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
-+ * James Cleverdon.
++ * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
+ *
-+ * Hacked to pieces for Xen by Chris Wright.
++ * Jun Nakajima <jun.nakajima@intel.com>
++ * Modified for Xen.
+ */
-+#include <linux/threads.h>
-+#include <linux/cpumask.h>
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/ctype.h>
++
+#include <linux/init.h>
-+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
++#include <linux/linkage.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/percpu.h>
++#include <linux/module.h>
++
++#include <asm/processor.h>
++#include <asm/proto.h>
+#include <asm/smp.h>
-+#include <asm/ipi.h>
-+#else
-+#include <asm/apic.h>
-+#include <asm/apicdef.h>
-+#include <asm/genapic.h>
-+#endif
-+#include <xen/evtchn.h>
++#include <asm/bootsetup.h>
++#include <asm/setup.h>
++#include <asm/desc.h>
++#include <asm/pgtable.h>
++#include <asm/sections.h>
+
-+DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
++unsigned long start_pfn;
+
-+static inline void __send_IPI_one(unsigned int cpu, int vector)
++/* Don't add a printk in there. printk relies on the PDA which is not initialized
++ yet. */
++#if 0
++static void __init clear_bss(void)
+{
-+ int irq = per_cpu(ipi_to_irq, cpu)[vector];
-+ BUG_ON(irq < 0);
-+ notify_remote_via_irq(irq);
++ memset(__bss_start, 0,
++ (unsigned long) __bss_stop - (unsigned long) __bss_start);
+}
++#endif
+
-+void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
++#define NEW_CL_POINTER 0x228 /* Relative to real mode data */
++#define OLD_CL_MAGIC_ADDR 0x90020
++#define OLD_CL_MAGIC 0xA33F
++#define OLD_CL_BASE_ADDR 0x90000
++#define OLD_CL_OFFSET 0x90022
++
++extern char saved_command_line[];
++
++static void __init copy_bootdata(char *real_mode_data)
+{
-+ int cpu;
++#ifndef CONFIG_XEN
++ int new_data;
++ char * command_line;
+
-+ switch (shortcut) {
-+ case APIC_DEST_SELF:
-+ __send_IPI_one(smp_processor_id(), vector);
-+ break;
-+ case APIC_DEST_ALLBUT:
-+ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
-+ if (cpu == smp_processor_id())
-+ continue;
-+ if (cpu_isset(cpu, cpu_online_map)) {
-+ __send_IPI_one(cpu, vector);
-+ }
-+ }
-+ break;
-+ case APIC_DEST_ALLINC:
-+ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
-+ if (cpu_isset(cpu, cpu_online_map)) {
-+ __send_IPI_one(cpu, vector);
-+ }
++ memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE);
++ new_data = *(int *) (x86_boot_params + NEW_CL_POINTER);
++ if (!new_data) {
++ if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
++ printk("so old bootloader that it does not support commandline?!\n");
++ return;
+ }
-+ break;
-+ default:
-+ printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
-+ vector);
-+ break;
++ new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
++ printk("old bootloader convention, maybe loadlin?\n");
+ }
++ command_line = (char *) ((u64)(new_data));
++ memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
++#else
++ int max_cmdline;
++
++ if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
++ max_cmdline = COMMAND_LINE_SIZE;
++ memcpy(saved_command_line, xen_start_info->cmd_line, max_cmdline);
++ saved_command_line[max_cmdline-1] = '\0';
++#endif
++ printk("Bootdata ok (command line is %s)\n", saved_command_line);
+}
+
-+static cpumask_t xen_target_cpus(void)
++static void __init setup_boot_cpu_data(void)
+{
-+ return cpu_online_map;
-+}
++ unsigned int dummy, eax;
+
-+/*
-+ * Set up the logical destination ID.
-+ * Do nothing, not called now.
-+ */
-+static void xen_init_apic_ldr(void)
-+{
-+ Dprintk("%s\n", __FUNCTION__);
-+ return;
-+}
++ /* get vendor info */
++ cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level,
++ (unsigned int *)&boot_cpu_data.x86_vendor_id[0],
++ (unsigned int *)&boot_cpu_data.x86_vendor_id[8],
++ (unsigned int *)&boot_cpu_data.x86_vendor_id[4]);
+
-+static void xen_send_IPI_allbutself(int vector)
-+{
-+ /*
-+ * if there are no other CPUs in the system then
-+ * we get an APIC send error if we try to broadcast.
-+ * thus we have to avoid sending IPIs in this case.
-+ */
-+ Dprintk("%s\n", __FUNCTION__);
-+ if (num_online_cpus() > 1)
-+ xen_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
++ /* get cpu type */
++ cpuid(1, &eax, &dummy, &dummy,
++ (unsigned int *) &boot_cpu_data.x86_capability);
++ boot_cpu_data.x86 = (eax >> 8) & 0xf;
++ boot_cpu_data.x86_model = (eax >> 4) & 0xf;
++ boot_cpu_data.x86_mask = eax & 0xf;
+}
+
-+static void xen_send_IPI_all(int vector)
-+{
-+ Dprintk("%s\n", __FUNCTION__);
-+ xen_send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
-+}
++#include <xen/interface/memory.h>
++unsigned long *machine_to_phys_mapping;
++EXPORT_SYMBOL(machine_to_phys_mapping);
++unsigned int machine_to_phys_order;
++EXPORT_SYMBOL(machine_to_phys_order);
+
-+static void xen_send_IPI_mask(cpumask_t cpumask, int vector)
++void __init x86_64_start_kernel(char * real_mode_data)
+{
-+ unsigned long mask = cpus_addr(cpumask)[0];
-+ unsigned int cpu;
-+ unsigned long flags;
++ struct xen_machphys_mapping mapping;
++ unsigned long machine_to_phys_nr_ents;
++ char *s;
++ int i;
+
-+ Dprintk("%s\n", __FUNCTION__);
-+ local_irq_save(flags);
-+ WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
++ setup_xen_features();
+
-+ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
-+ if (cpu_isset(cpu, cpumask)) {
-+ __send_IPI_one(cpu, vector);
-+ }
++ xen_start_info = (struct start_info *)real_mode_data;
++ if (!xen_feature(XENFEAT_auto_translated_physmap))
++ phys_to_machine_mapping =
++ (unsigned long *)xen_start_info->mfn_list;
++ start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
++ xen_start_info->nr_pt_frames;
++
++ machine_to_phys_mapping = (unsigned long *)MACH2PHYS_VIRT_START;
++ machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
++ if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
++ machine_to_phys_mapping = (unsigned long *)mapping.v_start;
++ machine_to_phys_nr_ents = mapping.max_mfn + 1;
+ }
-+ local_irq_restore(flags);
-+}
++ while ((1UL << machine_to_phys_order) < machine_to_phys_nr_ents )
++ machine_to_phys_order++;
+
-+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
-+static int xen_apic_id_registered(void)
-+{
-+ /* better be set */
-+ Dprintk("%s\n", __FUNCTION__);
-+ return physid_isset(smp_processor_id(), phys_cpu_present_map);
-+}
++#if 0
++ for (i = 0; i < 256; i++)
++ set_intr_gate(i, early_idt_handler);
++ asm volatile("lidt %0" :: "m" (idt_descr));
+#endif
+
-+static unsigned int xen_cpu_mask_to_apicid(cpumask_t cpumask)
-+{
-+ Dprintk("%s\n", __FUNCTION__);
-+ return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
-+}
-+
-+static unsigned int phys_pkg_id(int index_msb)
-+{
-+ u32 ebx;
++ /*
++ * This must be called really, really early:
++ */
++ lockdep_init();
+
-+ Dprintk("%s\n", __FUNCTION__);
-+ ebx = cpuid_ebx(1);
-+ return ((ebx >> 24) & 0xFF) >> index_msb;
-+}
++ for (i = 0; i < NR_CPUS; i++)
++ cpu_pda(i) = &boot_cpu_pda[i];
+
-+struct genapic apic_xen = {
-+ .name = "xen",
-+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
-+ .int_delivery_mode = dest_LowestPrio,
++ pda_init(0);
++ copy_bootdata(real_mode_data);
++#ifdef CONFIG_SMP
++ cpu_set(0, cpu_online_map);
+#endif
-+ .int_dest_mode = (APIC_DEST_LOGICAL != 0),
-+ .int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
-+ .target_cpus = xen_target_cpus,
-+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
-+ .apic_id_registered = xen_apic_id_registered,
++ s = strstr(saved_command_line, "earlyprintk=");
++ if (s != NULL)
++ setup_early_printk(strchr(s, '=') + 1);
++#ifdef CONFIG_NUMA
++ s = strstr(saved_command_line, "numa=");
++ if (s != NULL)
++ numa_setup(s+5);
+#endif
-+ .init_apic_ldr = xen_init_apic_ldr,
-+ .send_IPI_all = xen_send_IPI_all,
-+ .send_IPI_allbutself = xen_send_IPI_allbutself,
-+ .send_IPI_mask = xen_send_IPI_mask,
-+ .cpu_mask_to_apicid = xen_cpu_mask_to_apicid,
-+ .phys_pkg_id = phys_pkg_id,
-+};
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/head-xen.S linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/head-xen.S
---- linux-2.6.18.8/arch/x86_64/kernel/head-xen.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/head-xen.S 2008-02-15 16:21:55.000000000 -0800
++#ifdef CONFIG_X86_IO_APIC
++ if (strstr(saved_command_line, "disableapic"))
++ disable_apic = 1;
++#endif
++ /* You need early console to see that */
++ if (__pa_symbol(&_end) >= KERNEL_TEXT_SIZE)
++ panic("Kernel too big for kernel mapping\n");
++
++ setup_boot_cpu_data();
++ start_kernel();
++}
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/head-xen.S linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/head-xen.S
+--- linux-2.6.18.8/arch/x86_64/kernel/head-xen.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/head-xen.S 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,214 @@
+/*
+ * linux/arch/x86_64/kernel/head.S -- start in 32bit and switch to 64bit
@@ -43996,175 +44777,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/head-xen.S linux-2.6.18-xen-3.2.0/a
+ ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel")
+ ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic")
+ ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long, 1)
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/head64-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/head64-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/head64-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/head64-xen.c 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,162 @@
-+/*
-+ * linux/arch/x86_64/kernel/head64.c -- prepare to run common code
-+ *
-+ * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
-+ *
-+ * Jun Nakajima <jun.nakajima@intel.com>
-+ * Modified for Xen.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/linkage.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/percpu.h>
-+#include <linux/module.h>
-+
-+#include <asm/processor.h>
-+#include <asm/proto.h>
-+#include <asm/smp.h>
-+#include <asm/bootsetup.h>
-+#include <asm/setup.h>
-+#include <asm/desc.h>
-+#include <asm/pgtable.h>
-+#include <asm/sections.h>
-+
-+unsigned long start_pfn;
-+
-+/* Don't add a printk in there. printk relies on the PDA which is not initialized
-+ yet. */
-+#if 0
-+static void __init clear_bss(void)
-+{
-+ memset(__bss_start, 0,
-+ (unsigned long) __bss_stop - (unsigned long) __bss_start);
-+}
-+#endif
-+
-+#define NEW_CL_POINTER 0x228 /* Relative to real mode data */
-+#define OLD_CL_MAGIC_ADDR 0x90020
-+#define OLD_CL_MAGIC 0xA33F
-+#define OLD_CL_BASE_ADDR 0x90000
-+#define OLD_CL_OFFSET 0x90022
-+
-+extern char saved_command_line[];
-+
-+static void __init copy_bootdata(char *real_mode_data)
-+{
-+#ifndef CONFIG_XEN
-+ int new_data;
-+ char * command_line;
-+
-+ memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE);
-+ new_data = *(int *) (x86_boot_params + NEW_CL_POINTER);
-+ if (!new_data) {
-+ if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
-+ printk("so old bootloader that it does not support commandline?!\n");
-+ return;
-+ }
-+ new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
-+ printk("old bootloader convention, maybe loadlin?\n");
-+ }
-+ command_line = (char *) ((u64)(new_data));
-+ memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-+#else
-+ int max_cmdline;
-+
-+ if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
-+ max_cmdline = COMMAND_LINE_SIZE;
-+ memcpy(saved_command_line, xen_start_info->cmd_line, max_cmdline);
-+ saved_command_line[max_cmdline-1] = '\0';
-+#endif
-+ printk("Bootdata ok (command line is %s)\n", saved_command_line);
-+}
-+
-+static void __init setup_boot_cpu_data(void)
-+{
-+ unsigned int dummy, eax;
-+
-+ /* get vendor info */
-+ cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level,
-+ (unsigned int *)&boot_cpu_data.x86_vendor_id[0],
-+ (unsigned int *)&boot_cpu_data.x86_vendor_id[8],
-+ (unsigned int *)&boot_cpu_data.x86_vendor_id[4]);
-+
-+ /* get cpu type */
-+ cpuid(1, &eax, &dummy, &dummy,
-+ (unsigned int *) &boot_cpu_data.x86_capability);
-+ boot_cpu_data.x86 = (eax >> 8) & 0xf;
-+ boot_cpu_data.x86_model = (eax >> 4) & 0xf;
-+ boot_cpu_data.x86_mask = eax & 0xf;
-+}
-+
-+#include <xen/interface/memory.h>
-+unsigned long *machine_to_phys_mapping;
-+EXPORT_SYMBOL(machine_to_phys_mapping);
-+unsigned int machine_to_phys_order;
-+EXPORT_SYMBOL(machine_to_phys_order);
-+
-+void __init x86_64_start_kernel(char * real_mode_data)
-+{
-+ struct xen_machphys_mapping mapping;
-+ unsigned long machine_to_phys_nr_ents;
-+ char *s;
-+ int i;
-+
-+ setup_xen_features();
-+
-+ xen_start_info = (struct start_info *)real_mode_data;
-+ if (!xen_feature(XENFEAT_auto_translated_physmap))
-+ phys_to_machine_mapping =
-+ (unsigned long *)xen_start_info->mfn_list;
-+ start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
-+ xen_start_info->nr_pt_frames;
-+
-+ machine_to_phys_mapping = (unsigned long *)MACH2PHYS_VIRT_START;
-+ machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
-+ if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
-+ machine_to_phys_mapping = (unsigned long *)mapping.v_start;
-+ machine_to_phys_nr_ents = mapping.max_mfn + 1;
-+ }
-+ while ((1UL << machine_to_phys_order) < machine_to_phys_nr_ents )
-+ machine_to_phys_order++;
-+
-+#if 0
-+ for (i = 0; i < 256; i++)
-+ set_intr_gate(i, early_idt_handler);
-+ asm volatile("lidt %0" :: "m" (idt_descr));
-+#endif
-+
-+ /*
-+ * This must be called really, really early:
-+ */
-+ lockdep_init();
-+
-+ for (i = 0; i < NR_CPUS; i++)
-+ cpu_pda(i) = &boot_cpu_pda[i];
-+
-+ pda_init(0);
-+ copy_bootdata(real_mode_data);
-+#ifdef CONFIG_SMP
-+ cpu_set(0, cpu_online_map);
-+#endif
-+ s = strstr(saved_command_line, "earlyprintk=");
-+ if (s != NULL)
-+ setup_early_printk(strchr(s, '=') + 1);
-+#ifdef CONFIG_NUMA
-+ s = strstr(saved_command_line, "numa=");
-+ if (s != NULL)
-+ numa_setup(s+5);
-+#endif
-+#ifdef CONFIG_X86_IO_APIC
-+ if (strstr(saved_command_line, "disableapic"))
-+ disable_apic = 1;
-+#endif
-+ /* You need early console to see that */
-+ if (__pa_symbol(&_end) >= KERNEL_TEXT_SIZE)
-+ panic("Kernel too big for kernel mapping\n");
-+
-+ setup_boot_cpu_data();
-+ start_kernel();
-+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/init_task.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/init_task.c
---- linux-2.6.18.8/arch/x86_64/kernel/init_task.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/init_task.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/init_task.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/init_task.c
+--- linux-2.6.18.8/arch/x86_64/kernel/init_task.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/init_task.c 2008-08-21 11:36:07.000000000 +0200
@@ -37,6 +37,8 @@ union thread_union init_thread_union
struct task_struct init_task = INIT_TASK(init_task);
@@ -44181,9 +44796,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/init_task.c linux-2.6.18-xen-3.2.0/
+#endif
#define ALIGN_TO_4K __attribute__((section(".data.init_task")))
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/io_apic-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/io_apic-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/io_apic-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/io_apic-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/io_apic-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/io_apic-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/io_apic-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/io_apic-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,2262 @@
+/*
+ * Intel IO-APIC support for multi-Pentium hosts.
@@ -46447,9 +47062,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/io_apic-xen.c linux-2.6.18-xen-3.2.
+}
+#endif
+#endif /* !CONFIG_XEN */
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/ioport-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/ioport-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/ioport-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/ioport-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/ioport-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/ioport-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/ioport-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/ioport-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,100 @@
+/*
+ * linux/arch/x86_64/kernel/ioport.c
@@ -46551,9 +47166,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/ioport-xen.c linux-2.6.18-xen-3.2.0
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/irq-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/irq-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/irq-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/irq-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/irq-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/irq-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/irq-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/irq-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,197 @@
+/*
+ * linux/arch/x86_64/kernel/irq.c
@@ -46705,7 +47320,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/irq-xen.c linux-2.6.18-xen-3.2.0/ar
+
+ cpus_and(mask, irq_desc[irq].affinity, map);
+ if (any_online_cpu(mask) == NR_CPUS) {
-+ printk("Breaking affinity for irq %i\n", irq);
++ /*printk("Breaking affinity for irq %i\n", irq);*/
+ mask = map;
+ }
+ if (irq_desc[irq].chip->set_affinity)
@@ -46752,9 +47367,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/irq-xen.c linux-2.6.18-xen-3.2.0/ar
+ printk("unexpected IRQ trap at vector %02x\n", irq);
+}
+#endif
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/ldt-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/ldt-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/ldt-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/ldt-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/ldt-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/ldt-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/ldt-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/ldt-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,282 @@
+/*
+ * linux/arch/x86_64/kernel/ldt.c
@@ -47038,10 +47653,10 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/ldt-xen.c linux-2.6.18-xen-3.2.0/ar
+ }
+ return ret;
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/machine_kexec.c
---- linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/machine_kexec.c 2008-02-15 16:21:55.000000000 -0800
-@@ -15,6 +15,113 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/machine_kexec.c
+--- linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/machine_kexec.c 2008-08-21 11:36:07.000000000 +0200
+@@ -15,6 +15,128 @@
#include <asm/mmu_context.h>
#include <asm/io.h>
@@ -47134,6 +47749,21 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.
+ xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
+}
+
++int __init machine_kexec_setup_resources(struct resource *hypervisor,
++ struct resource *phys_cpus,
++ int nr_phys_cpus)
++{
++ int k;
++
++ /* The per-cpu crash note resources belong to the hypervisor resource */
++ for (k = 0; k < nr_phys_cpus; k++)
++ request_resource(hypervisor, phys_cpus + k);
++
++ return 0;
++}
++
++void machine_kexec_register_resources(struct resource *res) { ; }
++
+#else /* CONFIG_XEN */
+
+#define x__pmd(x) __pmd(x)
@@ -47155,7 +47785,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.
static void init_level2_page(pmd_t *level2p, unsigned long addr)
{
unsigned long end_addr;
-@@ -22,7 +129,7 @@ static void init_level2_page(pmd_t *leve
+@@ -22,7 +144,7 @@ static void init_level2_page(pmd_t *leve
addr &= PAGE_MASK;
end_addr = addr + PUD_SIZE;
while (addr < end_addr) {
@@ -47164,7 +47794,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.
addr += PMD_SIZE;
}
}
-@@ -47,12 +154,12 @@ static int init_level3_page(struct kimag
+@@ -47,12 +169,12 @@ static int init_level3_page(struct kimag
}
level2p = (pmd_t *)page_address(page);
init_level2_page(level2p, addr);
@@ -47179,7 +47809,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.
addr += PUD_SIZE;
}
out:
-@@ -83,12 +190,12 @@ static int init_level4_page(struct kimag
+@@ -83,12 +205,12 @@ static int init_level4_page(struct kimag
if (result) {
goto out;
}
@@ -47194,7 +47824,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.
addr += PGDIR_SIZE;
}
out:
-@@ -99,77 +206,29 @@ out:
+@@ -99,77 +221,29 @@ out:
static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
{
pgd_t *level4p;
@@ -47205,21 +47835,21 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.
-static void set_idt(void *newidt, u16 limit)
-{
- struct desc_ptr curidt;
-+ unsigned long x_end_pfn = end_pfn;
-
+-
- /* x86-64 supports unaliged loads & stores */
- curidt.size = limit;
- curidt.address = (unsigned long)newidt;
-+#ifdef CONFIG_XEN
-+ x_end_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
-+#endif
++ unsigned long x_end_pfn = end_pfn;
- __asm__ __volatile__ (
- "lidtq %0\n"
- : : "m" (curidt)
- );
-};
--
++#ifdef CONFIG_XEN
++ x_end_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
++#endif
+
-
-static void set_gdt(void *newgdt, u16 limit)
-{
@@ -47279,7 +47909,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.
return 0;
}
-@@ -178,51 +237,43 @@ void machine_kexec_cleanup(struct kimage
+@@ -178,51 +252,43 @@ void machine_kexec_cleanup(struct kimage
return;
}
@@ -47359,9 +47989,36 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/machine_kexec.c linux-2.6.18-xen-3.
+ image->start);
}
+#endif
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/mpparse-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/mpparse-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/mpparse-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/mpparse-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/Makefile
+--- linux-2.6.18.8/arch/x86_64/kernel/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -21,11 +21,13 @@ obj-$(CONFIG_MICROCODE) += microcode.o
+ obj-$(CONFIG_X86_CPUID) += cpuid.o
+ obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
+ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
++obj-$(CONFIG_X86_XEN_GENAPIC) += genapic.o genapic_xen.o
+ obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \
+ genapic.o genapic_cluster.o genapic_flat.o
+ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
+ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+-obj-$(CONFIG_PM) += suspend.o
++obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
++obj-$(CONFIG_ACPI_SLEEP) += suspend.o
+ obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o
+ obj-$(CONFIG_CPU_FREQ) += cpufreq/
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+@@ -55,3 +57,8 @@ i8237-y += ../../i386/kernel/i8237.o
+ msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
+ alternative-y += ../../i386/kernel/alternative.o
+
++time-$(CONFIG_XEN) += ../../i386/kernel/time.o
++pci-dma-$(CONFIG_XEN) += ../../i386/kernel/pci-dma.o
++
++disabled-obj-$(CONFIG_XEN) := i8259.o reboot.o smpboot.o trampoline.o
++%/head.o %/head.s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/mpparse-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/mpparse-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/mpparse-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/mpparse-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1011 @@
+/*
+ * Intel Multiprocessor Specification 1.1 and 1.4
@@ -48374,9 +49031,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/mpparse-xen.c linux-2.6.18-xen-3.2.
+
+#endif /*CONFIG_X86_IO_APIC*/
+#endif /*CONFIG_ACPI*/
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/pci-swiotlb-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/pci-swiotlb-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/pci-swiotlb-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/pci-swiotlb-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/pci-swiotlb-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/pci-swiotlb-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/pci-swiotlb-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/pci-swiotlb-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,55 @@
+/* Glue code to lib/swiotlb.c */
+
@@ -48433,10 +49090,10 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/pci-swiotlb-xen.c linux-2.6.18-xen-
+ }
+#endif
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/process-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/process-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/process-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/process-xen.c 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,833 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/process-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/process-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/process-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/process-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,848 @@
+/*
+ * linux/arch/x86-64/kernel/process.c
+ *
@@ -48930,8 +49587,14 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/process-xen.c linux-2.6.18-xen-3.2.
+#ifndef CONFIG_X86_NO_TSS
+ struct tss_struct *tss = &per_cpu(init_tss, cpu);
+#endif
++#if CONFIG_XEN_COMPAT > 0x030002
+ struct physdev_set_iopl iopl_op;
+ struct physdev_set_iobitmap iobmp_op;
++#else
++ struct physdev_op _pdo[2], *pdo = _pdo;
++#define iopl_op pdo->u.set_iopl
++#define iobmp_op pdo->u.set_iobitmap
++#endif
+ multicall_entry_t _mcl[8], *mcl = _mcl;
+
+ /*
@@ -48974,9 +49637,15 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/process-xen.c linux-2.6.18-xen-3.2.
+
+ if (unlikely(prev->iopl != next->iopl)) {
+ iopl_op.iopl = (next->iopl == 0) ? 1 : next->iopl;
++#if CONFIG_XEN_COMPAT > 0x030002
+ mcl->op = __HYPERVISOR_physdev_op;
+ mcl->args[0] = PHYSDEVOP_set_iopl;
+ mcl->args[1] = (unsigned long)&iopl_op;
++#else
++ mcl->op = __HYPERVISOR_physdev_op_compat;
++ pdo->cmd = PHYSDEVOP_set_iopl;
++ mcl->args[0] = (unsigned long)pdo++;
++#endif
+ mcl++;
+ }
+
@@ -48984,12 +49653,21 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/process-xen.c linux-2.6.18-xen-3.2.
+ set_xen_guest_handle(iobmp_op.bitmap,
+ (char *)next->io_bitmap_ptr);
+ iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0;
++#if CONFIG_XEN_COMPAT > 0x030002
+ mcl->op = __HYPERVISOR_physdev_op;
+ mcl->args[0] = PHYSDEVOP_set_iobitmap;
+ mcl->args[1] = (unsigned long)&iobmp_op;
++#else
++ mcl->op = __HYPERVISOR_physdev_op_compat;
++ pdo->cmd = PHYSDEVOP_set_iobitmap;
++ mcl->args[0] = (unsigned long)pdo++;
++#endif
+ mcl++;
+ }
+
++#if CONFIG_XEN_COMPAT <= 0x030002
++ BUG_ON(pdo > _pdo + ARRAY_SIZE(_pdo));
++#endif
+ BUG_ON(mcl > _mcl + ARRAY_SIZE(_mcl));
+ if (unlikely(HYPERVISOR_multicall_check(_mcl, mcl - _mcl, NULL)))
+ BUG();
@@ -49264,15 +49942,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/process-xen.c linux-2.6.18-xen-3.2.
+ sp -= get_random_int() % 8192;
+ return sp & ~0xf;
+}
-+
-+#ifndef CONFIG_SMP
-+void _restore_vcpu(void)
-+{
-+}
-+#endif
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/relocate_kernel.S linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/relocate_kernel.S
---- linux-2.6.18.8/arch/x86_64/kernel/relocate_kernel.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/relocate_kernel.S 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/relocate_kernel.S linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/relocate_kernel.S
+--- linux-2.6.18.8/arch/x86_64/kernel/relocate_kernel.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/relocate_kernel.S 2008-08-21 11:36:07.000000000 +0200
@@ -7,31 +7,195 @@
*/
@@ -49509,10 +50181,395 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/relocate_kernel.S linux-2.6.18-xen-
+idt_80:
+ .word 0 /* limit */
+ .quad 0 /* base */
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/setup-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/setup-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/setup-xen.c 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,1662 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/setup64-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/setup64-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/setup64-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/setup64-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,367 @@
++/*
++ * X86-64 specific CPU setup.
++ * Copyright (C) 1995 Linus Torvalds
++ * Copyright 2001, 2002, 2003 SuSE Labs / Andi Kleen.
++ * See setup.c for older changelog.
++ *
++ * Jun Nakajima <jun.nakajima@intel.com>
++ * Modified for Xen
++ *
++ */
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/string.h>
++#include <linux/bootmem.h>
++#include <linux/bitops.h>
++#include <linux/module.h>
++#include <asm/bootsetup.h>
++#include <asm/pda.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/desc.h>
++#include <asm/atomic.h>
++#include <asm/mmu_context.h>
++#include <asm/smp.h>
++#include <asm/i387.h>
++#include <asm/percpu.h>
++#include <asm/proto.h>
++#include <asm/sections.h>
++#ifdef CONFIG_XEN
++#include <asm/hypervisor.h>
++#endif
++
++char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
++
++cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
++
++struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly;
++EXPORT_SYMBOL(_cpu_pda);
++struct x8664_pda boot_cpu_pda[NR_CPUS] __cacheline_aligned;
++
++#ifndef CONFIG_X86_NO_IDT
++struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
++#endif
++
++char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
++
++unsigned long __supported_pte_mask __read_mostly = ~0UL;
++EXPORT_SYMBOL(__supported_pte_mask);
++static int do_not_nx __cpuinitdata = 0;
++
++/* noexec=on|off
++Control non executable mappings for 64bit processes.
++
++on Enable(default)
++off Disable
++*/
++int __init nonx_setup(char *str)
++{
++ if (!strncmp(str, "on", 2)) {
++ __supported_pte_mask |= _PAGE_NX;
++ do_not_nx = 0;
++ } else if (!strncmp(str, "off", 3)) {
++ do_not_nx = 1;
++ __supported_pte_mask &= ~_PAGE_NX;
++ }
++ return 1;
++}
++__setup("noexec=", nonx_setup); /* parsed early actually */
++
++int force_personality32 = 0;
++
++/* noexec32=on|off
++Control non executable heap for 32bit processes.
++To control the stack too use noexec=off
++
++on PROT_READ does not imply PROT_EXEC for 32bit processes
++off PROT_READ implies PROT_EXEC (default)
++*/
++static int __init nonx32_setup(char *str)
++{
++ if (!strcmp(str, "on"))
++ force_personality32 &= ~READ_IMPLIES_EXEC;
++ else if (!strcmp(str, "off"))
++ force_personality32 |= READ_IMPLIES_EXEC;
++ return 1;
++}
++__setup("noexec32=", nonx32_setup);
++
++/*
++ * Great future plan:
++ * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
++ * Always point %gs to its beginning
++ */
++void __init setup_per_cpu_areas(void)
++{
++ int i;
++ unsigned long size;
++
++#ifdef CONFIG_HOTPLUG_CPU
++ prefill_possible_map();
++#endif
++
++ /* Copy section for each CPU (we discard the original) */
++ size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
++#ifdef CONFIG_MODULES
++ if (size < PERCPU_ENOUGH_ROOM)
++ size = PERCPU_ENOUGH_ROOM;
++#endif
++
++ for_each_cpu_mask (i, cpu_possible_map) {
++ char *ptr;
++
++ if (!NODE_DATA(cpu_to_node(i))) {
++ printk("cpu with no node %d, num_online_nodes %d\n",
++ i, num_online_nodes());
++ ptr = alloc_bootmem(size);
++ } else {
++ ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
++ }
++ if (!ptr)
++ panic("Cannot allocate cpu data for CPU %d\n", i);
++ cpu_pda(i)->data_offset = ptr - __per_cpu_start;
++ memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
++ }
++}
++
++#ifdef CONFIG_XEN
++static void switch_pt(void)
++{
++ xen_pt_switch(__pa_symbol(init_level4_pgt));
++ xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
++}
++
++static void __cpuinit cpu_gdt_init(const struct desc_ptr *gdt_descr)
++{
++ unsigned long frames[16];
++ unsigned long va;
++ int f;
++
++ for (va = gdt_descr->address, f = 0;
++ va < gdt_descr->address + gdt_descr->size;
++ va += PAGE_SIZE, f++) {
++ frames[f] = virt_to_mfn(va);
++ make_page_readonly(
++ (void *)va, XENFEAT_writable_descriptor_tables);
++ }
++ if (HYPERVISOR_set_gdt(frames, (gdt_descr->size + 1) /
++ sizeof (struct desc_struct)))
++ BUG();
++}
++#else
++static void switch_pt(void)
++{
++ asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt)));
++}
++
++static void __cpuinit cpu_gdt_init(const struct desc_ptr *gdt_descr)
++{
++ asm volatile("lgdt %0" :: "m" (*gdt_descr));
++ asm volatile("lidt %0" :: "m" (idt_descr));
++}
++#endif
++
++void pda_init(int cpu)
++{
++ struct x8664_pda *pda = cpu_pda(cpu);
++
++ /* Setup up data that may be needed in __get_free_pages early */
++ asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
++#ifndef CONFIG_XEN
++ wrmsrl(MSR_GS_BASE, pda);
++#else
++ if (HYPERVISOR_set_segment_base(SEGBASE_GS_KERNEL,
++ (unsigned long)pda))
++ BUG();
++#endif
++ pda->cpunumber = cpu;
++ pda->irqcount = -1;
++ pda->kernelstack =
++ (unsigned long)stack_thread_info() - PDA_STACKOFFSET + THREAD_SIZE;
++ pda->active_mm = &init_mm;
++ pda->mmu_state = 0;
++
++ if (cpu == 0) {
++#ifdef CONFIG_XEN
++ xen_init_pt();
++#endif
++ /* others are initialized in smpboot.c */
++ pda->pcurrent = &init_task;
++ pda->irqstackptr = boot_cpu_stack;
++ } else {
++ pda->irqstackptr = (char *)
++ __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
++ if (!pda->irqstackptr)
++ panic("cannot allocate irqstack for cpu %d", cpu);
++ }
++
++ switch_pt();
++
++ pda->irqstackptr += IRQSTACKSIZE-64;
++}
++
++#ifndef CONFIG_X86_NO_TSS
++char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]
++__attribute__((section(".bss.page_aligned")));
++#endif
++
++/* May not be marked __init: used by software suspend */
++void syscall_init(void)
++{
++#ifndef CONFIG_XEN
++ /*
++ * LSTAR and STAR live in a bit strange symbiosis.
++ * They both write to the same internal register. STAR allows to set CS/DS
++ * but only a 32bit target. LSTAR sets the 64bit rip.
++ */
++ wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32);
++ wrmsrl(MSR_LSTAR, system_call);
++
++ /* Flags to clear on syscall */
++ wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000);
++#endif
++#ifdef CONFIG_IA32_EMULATION
++ syscall32_cpu_init ();
++#endif
++}
++
++void __cpuinit check_efer(void)
++{
++ unsigned long efer;
++
++ rdmsrl(MSR_EFER, efer);
++ if (!(efer & EFER_NX) || do_not_nx) {
++ __supported_pte_mask &= ~_PAGE_NX;
++ }
++}
++
++unsigned long kernel_eflags;
++
++/*
++ * cpu_init() initializes state that is per-CPU. Some data is already
++ * initialized (naturally) in the bootstrap process, such as the GDT
++ * and IDT. We reload them nevertheless, this function acts as a
++ * 'CPU state barrier', nothing should get across.
++ * A lot of state is already set up in PDA init.
++ */
++void __cpuinit cpu_init (void)
++{
++ int cpu = stack_smp_processor_id();
++#ifndef CONFIG_X86_NO_TSS
++ struct tss_struct *t = &per_cpu(init_tss, cpu);
++ struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu);
++ unsigned long v;
++ char *estacks = NULL;
++ unsigned i;
++#endif
++ struct task_struct *me;
++
++ /* CPU 0 is initialised in head64.c */
++ if (cpu != 0) {
++ pda_init(cpu);
++ zap_low_mappings(cpu);
++ }
++#ifndef CONFIG_X86_NO_TSS
++ else
++ estacks = boot_exception_stacks;
++#endif
++
++ me = current;
++
++ if (cpu_test_and_set(cpu, cpu_initialized))
++ panic("CPU#%d already initialized!\n", cpu);
++
++ printk("Initializing CPU#%d\n", cpu);
++
++ clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
++
++ /*
++ * Initialize the per-CPU GDT with the boot GDT,
++ * and set up the GDT descriptor:
++ */
++#ifndef CONFIG_XEN
++ if (cpu)
++ memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
++#endif
++
++ cpu_gdt_descr[cpu].size = GDT_SIZE;
++ cpu_gdt_init(&cpu_gdt_descr[cpu]);
++
++ memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8);
++ syscall_init();
++
++ wrmsrl(MSR_FS_BASE, 0);
++ wrmsrl(MSR_KERNEL_GS_BASE, 0);
++ barrier();
++
++ check_efer();
++
++#ifndef CONFIG_X86_NO_TSS
++ /*
++ * set up and load the per-CPU TSS
++ */
++ for (v = 0; v < N_EXCEPTION_STACKS; v++) {
++ if (cpu) {
++ static const unsigned int order[N_EXCEPTION_STACKS] = {
++ [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
++ [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
++ };
++
++ estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
++ if (!estacks)
++ panic("Cannot allocate exception stack %ld %d\n",
++ v, cpu);
++ }
++ switch (v + 1) {
++#if DEBUG_STKSZ > EXCEPTION_STKSZ
++ case DEBUG_STACK:
++ cpu_pda(cpu)->debugstack = (unsigned long)estacks;
++ estacks += DEBUG_STKSZ;
++ break;
++#endif
++ default:
++ estacks += EXCEPTION_STKSZ;
++ break;
++ }
++ orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
++ }
++
++ t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
++ /*
++ * <= is required because the CPU will access up to
++ * 8 bits beyond the end of the IO permission bitmap.
++ */
++ for (i = 0; i <= IO_BITMAP_LONGS; i++)
++ t->io_bitmap[i] = ~0UL;
++#endif
++
++ atomic_inc(&init_mm.mm_count);
++ me->active_mm = &init_mm;
++ if (me->mm)
++ BUG();
++ enter_lazy_tlb(&init_mm, me);
++
++#ifndef CONFIG_X86_NO_TSS
++ set_tss_desc(cpu, t);
++#endif
++#ifndef CONFIG_XEN
++ load_TR_desc();
++#endif
++ load_LDT(&init_mm.context);
++
++ /*
++ * Clear all 6 debug registers:
++ */
++
++ set_debugreg(0UL, 0);
++ set_debugreg(0UL, 1);
++ set_debugreg(0UL, 2);
++ set_debugreg(0UL, 3);
++ set_debugreg(0UL, 6);
++ set_debugreg(0UL, 7);
++
++ fpu_init();
++
++ raw_local_save_flags(kernel_eflags);
++}
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/setup.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/setup.c
+--- linux-2.6.18.8/arch/x86_64/kernel/setup.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/setup.c 2008-08-21 11:36:07.000000000 +0200
+@@ -122,7 +122,9 @@ struct resource standard_io_resources[]
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
+ { .name = "timer1", .start = 0x50, .end = 0x53,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
+- { .name = "keyboard", .start = 0x60, .end = 0x6f,
++ { .name = "keyboard", .start = 0x60, .end = 0x60,
++ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
++ { .name = "keyboard", .start = 0x64, .end = 0x64,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
+ { .name = "dma page reg", .start = 0x80, .end = 0x8f,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/setup-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/setup-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/setup-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/setup-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1654 @@
+/*
+ * linux/arch/x86-64/kernel/setup.c
+ *
@@ -49684,7 +50741,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
+ { .name = "timer1", .start = 0x50, .end = 0x53,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
-+ { .name = "keyboard", .start = 0x60, .end = 0x6f,
++ { .name = "keyboard", .start = 0x60, .end = 0x60,
++ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
++ { .name = "keyboard", .start = 0x64, .end = 0x64,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
+ { .name = "dma page reg", .start = 0x80, .end = 0x8f,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
@@ -50418,18 +51477,8 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/
+ */
+ probe_roms();
+#ifdef CONFIG_XEN
-+ if (is_initial_xendomain()) {
-+ struct xen_memory_map memmap;
-+
-+ memmap.nr_entries = E820MAX;
-+ set_xen_guest_handle(memmap.buffer, machine_e820.map);
-+
-+ if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap))
-+ BUG();
-+ machine_e820.nr_map = memmap.nr_entries;
-+
++ if (is_initial_xendomain())
+ e820_reserve_resources(machine_e820.map, machine_e820.nr_map);
-+ }
+#else
+ e820_reserve_resources(e820.map, e820.nr_map);
+#endif
@@ -51175,380 +52224,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/setup-xen.c linux-2.6.18-xen-3.2.0/
+}
+device_initcall(add_pcspkr);
+#endif
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/setup64-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/setup64-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/setup64-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/setup64-xen.c 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,367 @@
-+/*
-+ * X86-64 specific CPU setup.
-+ * Copyright (C) 1995 Linus Torvalds
-+ * Copyright 2001, 2002, 2003 SuSE Labs / Andi Kleen.
-+ * See setup.c for older changelog.
-+ *
-+ * Jun Nakajima <jun.nakajima@intel.com>
-+ * Modified for Xen
-+ *
-+ */
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/string.h>
-+#include <linux/bootmem.h>
-+#include <linux/bitops.h>
-+#include <linux/module.h>
-+#include <asm/bootsetup.h>
-+#include <asm/pda.h>
-+#include <asm/pgtable.h>
-+#include <asm/processor.h>
-+#include <asm/desc.h>
-+#include <asm/atomic.h>
-+#include <asm/mmu_context.h>
-+#include <asm/smp.h>
-+#include <asm/i387.h>
-+#include <asm/percpu.h>
-+#include <asm/proto.h>
-+#include <asm/sections.h>
-+#ifdef CONFIG_XEN
-+#include <asm/hypervisor.h>
-+#endif
-+
-+char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
-+
-+cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
-+
-+struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly;
-+EXPORT_SYMBOL(_cpu_pda);
-+struct x8664_pda boot_cpu_pda[NR_CPUS] __cacheline_aligned;
-+
-+#ifndef CONFIG_X86_NO_IDT
-+struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
-+#endif
-+
-+char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
-+
-+unsigned long __supported_pte_mask __read_mostly = ~0UL;
-+EXPORT_SYMBOL(__supported_pte_mask);
-+static int do_not_nx __cpuinitdata = 0;
-+
-+/* noexec=on|off
-+Control non executable mappings for 64bit processes.
-+
-+on Enable(default)
-+off Disable
-+*/
-+int __init nonx_setup(char *str)
-+{
-+ if (!strncmp(str, "on", 2)) {
-+ __supported_pte_mask |= _PAGE_NX;
-+ do_not_nx = 0;
-+ } else if (!strncmp(str, "off", 3)) {
-+ do_not_nx = 1;
-+ __supported_pte_mask &= ~_PAGE_NX;
-+ }
-+ return 1;
-+}
-+__setup("noexec=", nonx_setup); /* parsed early actually */
-+
-+int force_personality32 = 0;
-+
-+/* noexec32=on|off
-+Control non executable heap for 32bit processes.
-+To control the stack too use noexec=off
-+
-+on PROT_READ does not imply PROT_EXEC for 32bit processes
-+off PROT_READ implies PROT_EXEC (default)
-+*/
-+static int __init nonx32_setup(char *str)
-+{
-+ if (!strcmp(str, "on"))
-+ force_personality32 &= ~READ_IMPLIES_EXEC;
-+ else if (!strcmp(str, "off"))
-+ force_personality32 |= READ_IMPLIES_EXEC;
-+ return 1;
-+}
-+__setup("noexec32=", nonx32_setup);
-+
-+/*
-+ * Great future plan:
-+ * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
-+ * Always point %gs to its beginning
-+ */
-+void __init setup_per_cpu_areas(void)
-+{
-+ int i;
-+ unsigned long size;
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+ prefill_possible_map();
-+#endif
-+
-+ /* Copy section for each CPU (we discard the original) */
-+ size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
-+#ifdef CONFIG_MODULES
-+ if (size < PERCPU_ENOUGH_ROOM)
-+ size = PERCPU_ENOUGH_ROOM;
-+#endif
-+
-+ for_each_cpu_mask (i, cpu_possible_map) {
-+ char *ptr;
-+
-+ if (!NODE_DATA(cpu_to_node(i))) {
-+ printk("cpu with no node %d, num_online_nodes %d\n",
-+ i, num_online_nodes());
-+ ptr = alloc_bootmem(size);
-+ } else {
-+ ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
-+ }
-+ if (!ptr)
-+ panic("Cannot allocate cpu data for CPU %d\n", i);
-+ cpu_pda(i)->data_offset = ptr - __per_cpu_start;
-+ memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
-+ }
-+}
-+
-+#ifdef CONFIG_XEN
-+static void switch_pt(void)
-+{
-+ xen_pt_switch(__pa_symbol(init_level4_pgt));
-+ xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
-+}
-+
-+static void __cpuinit cpu_gdt_init(const struct desc_ptr *gdt_descr)
-+{
-+ unsigned long frames[16];
-+ unsigned long va;
-+ int f;
-+
-+ for (va = gdt_descr->address, f = 0;
-+ va < gdt_descr->address + gdt_descr->size;
-+ va += PAGE_SIZE, f++) {
-+ frames[f] = virt_to_mfn(va);
-+ make_page_readonly(
-+ (void *)va, XENFEAT_writable_descriptor_tables);
-+ }
-+ if (HYPERVISOR_set_gdt(frames, (gdt_descr->size + 1) /
-+ sizeof (struct desc_struct)))
-+ BUG();
-+}
-+#else
-+static void switch_pt(void)
-+{
-+ asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt)));
-+}
-+
-+static void __cpuinit cpu_gdt_init(const struct desc_ptr *gdt_descr)
-+{
-+ asm volatile("lgdt %0" :: "m" (*gdt_descr));
-+ asm volatile("lidt %0" :: "m" (idt_descr));
-+}
-+#endif
-+
-+void pda_init(int cpu)
-+{
-+ struct x8664_pda *pda = cpu_pda(cpu);
-+
-+ /* Setup up data that may be needed in __get_free_pages early */
-+ asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
-+#ifndef CONFIG_XEN
-+ wrmsrl(MSR_GS_BASE, pda);
-+#else
-+ if (HYPERVISOR_set_segment_base(SEGBASE_GS_KERNEL,
-+ (unsigned long)pda))
-+ BUG();
-+#endif
-+ pda->cpunumber = cpu;
-+ pda->irqcount = -1;
-+ pda->kernelstack =
-+ (unsigned long)stack_thread_info() - PDA_STACKOFFSET + THREAD_SIZE;
-+ pda->active_mm = &init_mm;
-+ pda->mmu_state = 0;
-+
-+ if (cpu == 0) {
-+#ifdef CONFIG_XEN
-+ xen_init_pt();
-+#endif
-+ /* others are initialized in smpboot.c */
-+ pda->pcurrent = &init_task;
-+ pda->irqstackptr = boot_cpu_stack;
-+ } else {
-+ pda->irqstackptr = (char *)
-+ __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
-+ if (!pda->irqstackptr)
-+ panic("cannot allocate irqstack for cpu %d", cpu);
-+ }
-+
-+ switch_pt();
-+
-+ pda->irqstackptr += IRQSTACKSIZE-64;
-+}
-+
-+#ifndef CONFIG_X86_NO_TSS
-+char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]
-+__attribute__((section(".bss.page_aligned")));
-+#endif
-+
-+/* May not be marked __init: used by software suspend */
-+void syscall_init(void)
-+{
-+#ifndef CONFIG_XEN
-+ /*
-+ * LSTAR and STAR live in a bit strange symbiosis.
-+ * They both write to the same internal register. STAR allows to set CS/DS
-+ * but only a 32bit target. LSTAR sets the 64bit rip.
-+ */
-+ wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32);
-+ wrmsrl(MSR_LSTAR, system_call);
-+
-+ /* Flags to clear on syscall */
-+ wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000);
-+#endif
-+#ifdef CONFIG_IA32_EMULATION
-+ syscall32_cpu_init ();
-+#endif
-+}
-+
-+void __cpuinit check_efer(void)
-+{
-+ unsigned long efer;
-+
-+ rdmsrl(MSR_EFER, efer);
-+ if (!(efer & EFER_NX) || do_not_nx) {
-+ __supported_pte_mask &= ~_PAGE_NX;
-+ }
-+}
-+
-+unsigned long kernel_eflags;
-+
-+/*
-+ * cpu_init() initializes state that is per-CPU. Some data is already
-+ * initialized (naturally) in the bootstrap process, such as the GDT
-+ * and IDT. We reload them nevertheless, this function acts as a
-+ * 'CPU state barrier', nothing should get across.
-+ * A lot of state is already set up in PDA init.
-+ */
-+void __cpuinit cpu_init (void)
-+{
-+ int cpu = stack_smp_processor_id();
-+#ifndef CONFIG_X86_NO_TSS
-+ struct tss_struct *t = &per_cpu(init_tss, cpu);
-+ struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu);
-+ unsigned long v;
-+ char *estacks = NULL;
-+ unsigned i;
-+#endif
-+ struct task_struct *me;
-+
-+ /* CPU 0 is initialised in head64.c */
-+ if (cpu != 0) {
-+ pda_init(cpu);
-+ zap_low_mappings(cpu);
-+ }
-+#ifndef CONFIG_X86_NO_TSS
-+ else
-+ estacks = boot_exception_stacks;
-+#endif
-+
-+ me = current;
-+
-+ if (cpu_test_and_set(cpu, cpu_initialized))
-+ panic("CPU#%d already initialized!\n", cpu);
-+
-+ printk("Initializing CPU#%d\n", cpu);
-+
-+ clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
-+
-+ /*
-+ * Initialize the per-CPU GDT with the boot GDT,
-+ * and set up the GDT descriptor:
-+ */
-+#ifndef CONFIG_XEN
-+ if (cpu)
-+ memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
-+#endif
-+
-+ cpu_gdt_descr[cpu].size = GDT_SIZE;
-+ cpu_gdt_init(&cpu_gdt_descr[cpu]);
-+
-+ memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8);
-+ syscall_init();
-+
-+ wrmsrl(MSR_FS_BASE, 0);
-+ wrmsrl(MSR_KERNEL_GS_BASE, 0);
-+ barrier();
-+
-+ check_efer();
-+
-+#ifndef CONFIG_X86_NO_TSS
-+ /*
-+ * set up and load the per-CPU TSS
-+ */
-+ for (v = 0; v < N_EXCEPTION_STACKS; v++) {
-+ if (cpu) {
-+ static const unsigned int order[N_EXCEPTION_STACKS] = {
-+ [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
-+ [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
-+ };
-+
-+ estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
-+ if (!estacks)
-+ panic("Cannot allocate exception stack %ld %d\n",
-+ v, cpu);
-+ }
-+ switch (v + 1) {
-+#if DEBUG_STKSZ > EXCEPTION_STKSZ
-+ case DEBUG_STACK:
-+ cpu_pda(cpu)->debugstack = (unsigned long)estacks;
-+ estacks += DEBUG_STKSZ;
-+ break;
-+#endif
-+ default:
-+ estacks += EXCEPTION_STKSZ;
-+ break;
-+ }
-+ orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
-+ }
-+
-+ t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
-+ /*
-+ * <= is required because the CPU will access up to
-+ * 8 bits beyond the end of the IO permission bitmap.
-+ */
-+ for (i = 0; i <= IO_BITMAP_LONGS; i++)
-+ t->io_bitmap[i] = ~0UL;
-+#endif
-+
-+ atomic_inc(&init_mm.mm_count);
-+ me->active_mm = &init_mm;
-+ if (me->mm)
-+ BUG();
-+ enter_lazy_tlb(&init_mm, me);
-+
-+#ifndef CONFIG_X86_NO_TSS
-+ set_tss_desc(cpu, t);
-+#endif
-+#ifndef CONFIG_XEN
-+ load_TR_desc();
-+#endif
-+ load_LDT(&init_mm.context);
-+
-+ /*
-+ * Clear all 6 debug registers:
-+ */
-+
-+ set_debugreg(0UL, 0);
-+ set_debugreg(0UL, 1);
-+ set_debugreg(0UL, 2);
-+ set_debugreg(0UL, 3);
-+ set_debugreg(0UL, 6);
-+ set_debugreg(0UL, 7);
-+
-+ fpu_init();
-+
-+ raw_local_save_flags(kernel_eflags);
-+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/signal.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/signal.c
---- linux-2.6.18.8/arch/x86_64/kernel/signal.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/signal.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/signal.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/signal.c
+--- linux-2.6.18.8/arch/x86_64/kernel/signal.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/signal.c 2008-08-21 11:36:07.000000000 +0200
@@ -38,37 +38,6 @@ int ia32_setup_frame(int sig, struct k_s
sigset_t *set, struct pt_regs * regs);
@@ -51704,10 +52382,10 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/signal.c linux-2.6.18-xen-3.2.0/arc
}
void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/smp-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/smp-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/smp-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/smp-xen.c 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,577 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/smp-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/smp-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/smp-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/smp-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,575 @@
+/*
+ * Intel SMP support routines.
+ *
@@ -51780,7 +52458,6 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/smp-xen.c linux-2.6.18-xen-3.2.0/ar
+ to a full cache line because other CPUs can access it and we don't
+ want false sharing in the per cpu data segment. */
+static DEFINE_PER_CPU(union smp_flush_state, flush_state);
-+#endif
+
+/*
+ * We cannot call mmdrop() because we are in interrupt context,
@@ -51794,7 +52471,6 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/smp-xen.c linux-2.6.18-xen-3.2.0/ar
+ load_cr3(swapper_pg_dir);
+}
+
-+#ifndef CONFIG_XEN
+/*
+ *
+ * The flush IPI assumes that a thread switch happens in this order:
@@ -52285,9 +52961,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/smp-xen.c linux-2.6.18-xen-3.2.0/ar
+ return 0; /* Should not happen */
+#endif
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/suspend.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/suspend.c
---- linux-2.6.18.8/arch/x86_64/kernel/suspend.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/suspend.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/suspend.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/suspend.c
+--- linux-2.6.18.8/arch/x86_64/kernel/suspend.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/suspend.c 2008-08-21 11:36:07.000000000 +0200
@@ -114,12 +114,14 @@ void restore_processor_state(void)
void fix_processor_context(void)
@@ -52303,9 +52979,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/suspend.c linux-2.6.18-xen-3.2.0/ar
syscall_init(); /* This sets MSR_*STAR and related */
load_TR_desc(); /* This does ltr */
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/traps-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/traps-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/traps-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/traps-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/traps-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/traps-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/traps-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/traps-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1173 @@
+/*
+ * linux/arch/x86-64/traps.c
@@ -53397,7 +54073,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/traps-xen.c linux-2.6.18-xen-3.2.0/
+ * NB. All these are "interrupt gates" (i.e. events_mask is set) because we
+ * specify <dpl>|4 in the second field.
+ */
-+static trap_info_t trap_table[] = {
++static trap_info_t __cpuinitdata trap_table[] = {
+ { 0, 0|4, __KERNEL_CS, (unsigned long)divide_error },
+ { 1, 0|4, __KERNEL_CS, (unsigned long)debug },
+ { 3, 3|4, __KERNEL_CS, (unsigned long)int3 },
@@ -53438,7 +54114,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/traps-xen.c linux-2.6.18-xen-3.2.0/
+ cpu_init();
+}
+
-+void smp_trap_init(trap_info_t *trap_ctxt)
++void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
+{
+ const trap_info_t *t = trap_table;
+
@@ -53480,9 +54156,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/traps-xen.c linux-2.6.18-xen-3.2.0/
+}
+__setup("call_trace=", call_trace_setup);
+#endif
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/vmlinux.lds.S linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/vmlinux.lds.S
---- linux-2.6.18.8/arch/x86_64/kernel/vmlinux.lds.S 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/vmlinux.lds.S 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/vmlinux.lds.S linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/vmlinux.lds.S
+--- linux-2.6.18.8/arch/x86_64/kernel/vmlinux.lds.S 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/vmlinux.lds.S 2008-08-21 11:36:07.000000000 +0200
@@ -13,6 +13,13 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86
OUTPUT_ARCH(i386:x86-64)
ENTRY(phys_startup_64)
@@ -53565,9 +54241,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/vmlinux.lds.S linux-2.6.18-xen-3.2.
+
+ NOTES
}
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/vsyscall-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/vsyscall-xen.c
---- linux-2.6.18.8/arch/x86_64/kernel/vsyscall-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/vsyscall-xen.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/vsyscall-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/vsyscall-xen.c
+--- linux-2.6.18.8/arch/x86_64/kernel/vsyscall-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/vsyscall-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,227 @@
+/*
+ * linux/arch/x86_64/kernel/vsyscall.c
@@ -53796,10 +54472,10 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/vsyscall-xen.c linux-2.6.18-xen-3.2
+}
+
+__initcall(vsyscall_init);
-diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/xen_entry.S linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/xen_entry.S
---- linux-2.6.18.8/arch/x86_64/kernel/xen_entry.S 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/kernel/xen_entry.S 2008-02-15 16:21:55.000000000 -0800
-@@ -0,0 +1,40 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/xen_entry.S linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/xen_entry.S
+--- linux-2.6.18.8/arch/x86_64/kernel/xen_entry.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/kernel/xen_entry.S 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,36 @@
+/*
+ * Copied from arch/xen/i386/kernel/entry.S
+ */
@@ -53836,38 +54512,57 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/kernel/xen_entry.S linux-2.6.18-xen-3.2.0/
+ XEN_LOCKED_UNBLOCK_EVENTS(reg) ; \
+ XEN_PUT_VCPU_INFO(reg)
+#define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg)
-+
-+VGCF_IN_SYSCALL = (1<<8)
-+
-+
-diff -rpuN linux-2.6.18.8/arch/x86_64/lib/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/lib/Makefile
---- linux-2.6.18.8/arch/x86_64/lib/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/lib/Makefile 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/lib/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/lib/Makefile
+--- linux-2.6.18.8/arch/x86_64/lib/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/lib/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -10,3 +10,4 @@ lib-y := csum-partial.o csum-copy.o csum
usercopy.o getuser.o putuser.o \
thunk.o clear_page.o copy_page.o bitstr.o bitops.o
lib-y += memcpy.o memmove.o memset.o copy_user.o
+lib-$(CONFIG_XEN_SCRUB_PAGES) += scrub.o
-diff -rpuN linux-2.6.18.8/arch/x86_64/lib/scrub.c linux-2.6.18-xen-3.2.0/arch/x86_64/lib/scrub.c
---- linux-2.6.18.8/arch/x86_64/lib/scrub.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/lib/scrub.c 2008-02-15 16:21:55.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/lib/scrub.c linux-2.6.18-xen-3.3.0/arch/x86_64/lib/scrub.c
+--- linux-2.6.18.8/arch/x86_64/lib/scrub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/lib/scrub.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1 @@
+#include "../../i386/lib/scrub.c"
-diff -rpuN linux-2.6.18.8/arch/x86_64/mm/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/mm/Makefile
---- linux-2.6.18.8/arch/x86_64/mm/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/mm/Makefile 2008-02-15 16:21:56.000000000 -0800
-@@ -7,5 +7,8 @@ obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpag
- obj-$(CONFIG_NUMA) += numa.o
- obj-$(CONFIG_K8_NUMA) += k8topology.o
- obj-$(CONFIG_ACPI_NUMA) += srat.o
-+obj-$(CONFIG_XEN) += hypervisor.o
+diff -rpuN linux-2.6.18.8/arch/x86_64/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/Makefile
+--- linux-2.6.18.8/arch/x86_64/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -71,9 +71,22 @@ drivers-$(CONFIG_OPROFILE) += arch/x86_
- hugetlbpage-y = ../../i386/mm/hugetlbpage.o
-+ioremap-$(CONFIG_XEN) := ../../i386/mm/ioremap.o
-+hypervisor-y := ../../i386/mm/hypervisor.o
-diff -rpuN linux-2.6.18.8/arch/x86_64/mm/fault-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/mm/fault-xen.c
---- linux-2.6.18.8/arch/x86_64/mm/fault-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/mm/fault-xen.c 2008-02-15 16:21:56.000000000 -0800
+ boot := arch/x86_64/boot
+
+-PHONY += bzImage bzlilo install archmrproper \
++PHONY += bzImage bzlilo vmlinuz install archmrproper \
+ fdimage fdimage144 fdimage288 isoimage archclean
+
++ifdef CONFIG_XEN
++CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
++ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS)
++LDFLAGS_vmlinux := -e startup_64
++#Default target when executing "make"
++all: vmlinuz
++
++BOOTIMAGE := $(boot)/vmlinuz
++KBUILD_IMAGE := $(BOOTIMAGE)
++
++vmlinuz: vmlinux
++ $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
++else
+ #Default target when executing "make"
+ all: bzImage
+
+@@ -91,6 +104,7 @@ bzdisk: vmlinux
+
+ fdimage fdimage144 fdimage288 isoimage: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
++endif
+
+ install:
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
+diff -rpuN linux-2.6.18.8/arch/x86_64/mm/fault-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/mm/fault-xen.c
+--- linux-2.6.18.8/arch/x86_64/mm/fault-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/mm/fault-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,724 @@
+/*
+ * linux/arch/x86-64/mm/fault.c
@@ -54593,10 +55288,10 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/fault-xen.c linux-2.6.18-xen-3.2.0/arch
+ return 1;
+}
+__setup("pagefaulttrace", enable_pagefaulttrace);
-diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/mm/init-xen.c
---- linux-2.6.18.8/arch/x86_64/mm/init-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/mm/init-xen.c 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,1207 @@
+diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/mm/init-xen.c
+--- linux-2.6.18.8/arch/x86_64/mm/init-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/mm/init-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1213 @@
+/*
+ * linux/arch/x86_64/mm/init.c
+ *
@@ -54658,6 +55353,8 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+EXPORT_SYMBOL(__kernel_page_user);
+#endif
+
++int after_bootmem;
++
+extern unsigned long *contiguous_bitmap;
+
+static unsigned long dma_reserve __initdata;
@@ -54682,6 +55379,8 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+ pte_t pte, *ptep;
+ unsigned long *page = (unsigned long *) init_level4_pgt;
+
++ BUG_ON(after_bootmem);
++
+ if (xen_feature(feature))
+ return;
+
@@ -54806,7 +55505,6 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+ printk(KERN_INFO "%lu pages swap cached\n",cached);
+}
+
-+int after_bootmem;
+
+static __init void *spp_getpage(void)
+{
@@ -54921,6 +55619,14 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+ new_pte = pfn_pte_ma(phys >> PAGE_SHIFT, prot);
+
+ pte = pte_offset_kernel(pmd, vaddr);
++ if (!pte_none(*pte) &&
++#ifdef CONFIG_ACPI
++ /* __acpi_map_table() fails to properly call clear_fixmap() */
++ (vaddr < __fix_to_virt(FIX_ACPI_END) ||
++ vaddr > __fix_to_virt(FIX_ACPI_BEGIN)) &&
++#endif
++ __pte_val(*pte) != (__pte_val(new_pte) & __supported_pte_mask))
++ pte_ERROR(*pte);
+ set_pte(pte, new_pte);
+
+ /*
@@ -54972,11 +55678,6 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+
+#define PTE_SIZE PAGE_SIZE
+
-+static inline void __set_pte(pte_t *dst, pte_t val)
-+{
-+ *dst = val;
-+}
-+
+static inline int make_readonly(unsigned long paddr)
+{
+ extern char __vsyscall_0;
@@ -55045,28 +55746,28 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+ unsigned long pte_phys;
+ pte_t *pte, *pte_save;
+
-+ if (address >= end) {
-+ if (!after_bootmem)
-+ for (; i < PTRS_PER_PMD; i++, pmd++)
-+ set_pmd(pmd, __pmd(0));
++ if (address >= end)
+ break;
-+ }
+ pte = alloc_static_page(&pte_phys);
+ pte_save = pte;
+ for (k = 0; k < PTRS_PER_PTE; pte++, k++, address += PTE_SIZE) {
+ unsigned long pteval = address | _PAGE_NX | _KERNPG_TABLE;
+
-+ if ((address >= end) ||
-+ ((address >> PAGE_SHIFT) >=
-+ xen_start_info->nr_pages))
++ if (address >= (after_bootmem
++ ? end
++ : xen_start_info->nr_pages << PAGE_SHIFT))
+ pteval = 0;
+ else if (make_readonly(address))
+ pteval &= ~_PAGE_RW;
-+ __set_pte(pte, __pte(pteval & __supported_pte_mask));
++ set_pte(pte, __pte(pteval & __supported_pte_mask));
++ }
++ if (!after_bootmem) {
++ early_make_page_readonly(pte_save, XENFEAT_writable_page_tables);
++ *pmd = __pmd(pte_phys | _KERNPG_TABLE);
++ } else {
++ make_page_readonly(pte_save, XENFEAT_writable_page_tables);
++ set_pmd(pmd, __pmd(pte_phys | _KERNPG_TABLE));
+ }
-+ pte = pte_save;
-+ early_make_page_readonly(pte, XENFEAT_writable_page_tables);
-+ set_pmd(pmd, __pmd(pte_phys | _KERNPG_TABLE));
+ }
+}
+
@@ -55103,11 +55804,13 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+ break;
+
+ pmd = alloc_static_page(&pmd_phys);
-+ early_make_page_readonly(pmd, XENFEAT_writable_page_tables);
++
+ spin_lock(&init_mm.page_table_lock);
-+ set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
++ *pud = __pud(pmd_phys | _KERNPG_TABLE);
+ phys_pmd_init(pmd, paddr, end);
+ spin_unlock(&init_mm.page_table_lock);
++
++ early_make_page_readonly(pmd, XENFEAT_writable_page_tables);
+ }
+ __flush_tlb();
+}
@@ -55338,20 +56041,18 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+ pgd_t *pgd = pgd_offset_k(start);
+ pud_t *pud;
+
-+ if (after_bootmem) {
++ if (after_bootmem)
+ pud = pud_offset(pgd, start & PGDIR_MASK);
-+ make_page_readonly(pud, XENFEAT_writable_page_tables);
-+ pud_phys = __pa(pud);
-+ } else {
++ else
+ pud = alloc_static_page(&pud_phys);
-+ early_make_page_readonly(pud, XENFEAT_writable_page_tables);
-+ }
+ next = start + PGDIR_SIZE;
+ if (next > end)
+ next = end;
+ phys_pud_init(pud, __pa(start), __pa(next));
-+ if (!after_bootmem)
++ if (!after_bootmem) {
++ early_make_page_readonly(pud, XENFEAT_writable_page_tables);
+ set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
++ }
+ }
+
+ if (!after_bootmem) {
@@ -55804,9 +56505,21 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/init-xen.c linux-2.6.18-xen-3.2.0/arch/
+{
+ return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
+}
-diff -rpuN linux-2.6.18.8/arch/x86_64/mm/pageattr-xen.c linux-2.6.18-xen-3.2.0/arch/x86_64/mm/pageattr-xen.c
---- linux-2.6.18.8/arch/x86_64/mm/pageattr-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/mm/pageattr-xen.c 2008-02-15 16:21:56.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/mm/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/mm/Makefile
+--- linux-2.6.18.8/arch/x86_64/mm/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/mm/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -7,5 +7,8 @@ obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpag
+ obj-$(CONFIG_NUMA) += numa.o
+ obj-$(CONFIG_K8_NUMA) += k8topology.o
+ obj-$(CONFIG_ACPI_NUMA) += srat.o
++obj-$(CONFIG_XEN) += hypervisor.o
+
+ hugetlbpage-y = ../../i386/mm/hugetlbpage.o
++ioremap-$(CONFIG_XEN) := ../../i386/mm/ioremap.o
++hypervisor-y := ../../i386/mm/hypervisor.o
+diff -rpuN linux-2.6.18.8/arch/x86_64/mm/pageattr-xen.c linux-2.6.18-xen-3.3.0/arch/x86_64/mm/pageattr-xen.c
+--- linux-2.6.18.8/arch/x86_64/mm/pageattr-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/mm/pageattr-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,502 @@
+/*
+ * Copyright 2002 Andi Kleen, SuSE Labs.
@@ -56086,7 +56799,7 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/pageattr-xen.c linux-2.6.18-xen-3.2.0/a
+}
+#endif /* CONFIG_XEN */
+
-+static inline pte_t *lookup_address(unsigned long address)
++pte_t *lookup_address(unsigned long address)
+{
+ pgd_t *pgd = pgd_offset_k(address);
+ pud_t *pud;
@@ -56310,9 +57023,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/mm/pageattr-xen.c linux-2.6.18-xen-3.2.0/a
+
+EXPORT_SYMBOL(change_page_attr);
+EXPORT_SYMBOL(global_flush_tlb);
-diff -rpuN linux-2.6.18.8/arch/x86_64/oprofile/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/oprofile/Makefile
---- linux-2.6.18.8/arch/x86_64/oprofile/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/oprofile/Makefile 2008-02-15 16:21:56.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/oprofile/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/oprofile/Makefile
+--- linux-2.6.18.8/arch/x86_64/oprofile/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/oprofile/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -11,9 +11,15 @@ DRIVER_OBJS = $(addprefix ../../../drive
oprofilefs.o oprofile_stats.o \
timer_int.o )
@@ -56331,9 +57044,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/oprofile/Makefile linux-2.6.18-xen-3.2.0/a
+endif
+oprofile-y = $(DRIVER_OBJS) $(XENOPROF_COMMON_OBJS) \
+ $(addprefix ../../i386/oprofile/, $(OPROFILE-y))
-diff -rpuN linux-2.6.18.8/arch/x86_64/pci/Makefile linux-2.6.18-xen-3.2.0/arch/x86_64/pci/Makefile
---- linux-2.6.18.8/arch/x86_64/pci/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/arch/x86_64/pci/Makefile 2008-02-15 16:21:56.000000000 -0800
+diff -rpuN linux-2.6.18.8/arch/x86_64/pci/Makefile linux-2.6.18-xen-3.3.0/arch/x86_64/pci/Makefile
+--- linux-2.6.18.8/arch/x86_64/pci/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/arch/x86_64/pci/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -15,8 +15,13 @@ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
obj-$(CONFIG_NUMA) += k8-bus.o
@@ -56348,9 +57061,9 @@ diff -rpuN linux-2.6.18.8/arch/x86_64/pci/Makefile linux-2.6.18-xen-3.2.0/arch/x
legacy-y += ../../i386/pci/legacy.o
irq-y += ../../i386/pci/irq.o
common-y += ../../i386/pci/common.o
-diff -rpuN linux-2.6.18.8/block/elevator.c linux-2.6.18-xen-3.2.0/block/elevator.c
---- linux-2.6.18.8/block/elevator.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/block/elevator.c 2008-02-15 16:21:56.000000000 -0800
+diff -rpuN linux-2.6.18.8/block/elevator.c linux-2.6.18-xen-3.3.0/block/elevator.c
+--- linux-2.6.18.8/block/elevator.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/block/elevator.c 2008-08-21 11:36:07.000000000 +0200
@@ -493,6 +493,16 @@ struct request *elv_next_request(request
int ret;
@@ -56368,9 +57081,9 @@ diff -rpuN linux-2.6.18.8/block/elevator.c linux-2.6.18-xen-3.2.0/block/elevator
if (!(rq->flags & REQ_STARTED)) {
elevator_t *e = q->elevator;
-diff -rpuN linux-2.6.18.8/block/ll_rw_blk.c linux-2.6.18-xen-3.2.0/block/ll_rw_blk.c
---- linux-2.6.18.8/block/ll_rw_blk.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/block/ll_rw_blk.c 2008-02-15 16:21:56.000000000 -0800
+diff -rpuN linux-2.6.18.8/block/ll_rw_blk.c linux-2.6.18-xen-3.3.0/block/ll_rw_blk.c
+--- linux-2.6.18.8/block/ll_rw_blk.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/block/ll_rw_blk.c 2008-08-21 11:36:07.000000000 +0200
@@ -483,9 +483,12 @@ static inline struct request *start_orde
* Queue ordered sequence. As we stack them at the head, we
* need to queue in reverse order. Note that we rely on that
@@ -56466,9 +57179,9 @@ diff -rpuN linux-2.6.18.8/block/ll_rw_blk.c linux-2.6.18-xen-3.2.0/block/ll_rw_b
if (nr_bytes >= bio->bi_size) {
req->bio = bio->bi_next;
nbytes = bio->bi_size;
-diff -rpuN linux-2.6.18.8/buildconfigs/conf.linux-native/00_xen_to_native linux-2.6.18-xen-3.2.0/buildconfigs/conf.linux-native/00_xen_to_native
---- linux-2.6.18.8/buildconfigs/conf.linux-native/00_xen_to_native 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/conf.linux-native/00_xen_to_native 2008-02-15 16:21:56.000000000 -0800
+diff -rpuN linux-2.6.18.8/buildconfigs/conf.linux-native/00_xen_to_native linux-2.6.18-xen-3.3.0/buildconfigs/conf.linux-native/00_xen_to_native
+--- linux-2.6.18.8/buildconfigs/conf.linux-native/00_xen_to_native 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/conf.linux-native/00_xen_to_native 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,86 @@
+# Linux kernel version: 2.6.16.13-native
+# Mon May 15 10:59:54 2006
@@ -56556,9 +57269,9 @@ diff -rpuN linux-2.6.18.8/buildconfigs/conf.linux-native/00_xen_to_native linux-
+CONFIG_X86_HT=y
+# CONFIG_X86_NO_TSS is not set
+# CONFIG_X86_NO_IDT is not set
-diff -rpuN linux-2.6.18.8/buildconfigs/create_config.sh linux-2.6.18-xen-3.2.0/buildconfigs/create_config.sh
---- linux-2.6.18.8/buildconfigs/create_config.sh 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/create_config.sh 2008-02-15 16:21:56.000000000 -0800
+diff -rpuN linux-2.6.18.8/buildconfigs/create_config.sh linux-2.6.18-xen-3.3.0/buildconfigs/create_config.sh
+--- linux-2.6.18.8/buildconfigs/create_config.sh 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/create_config.sh 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,54 @@
+#!/bin/sh
+set -e
@@ -56614,14 +57327,14 @@ diff -rpuN linux-2.6.18.8/buildconfigs/create_config.sh linux-2.6.18-xen-3.2.0/b
+ done
+ fi
+done
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_ia64 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen0_ia64
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_ia64 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen0_ia64 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,1697 @@
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_ia64 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen0_ia64
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_ia64 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen0_ia64 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1703 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
-+# Mon Dec 17 13:38:33 2007
++# Tue Feb 19 11:20:09 2008
+#
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
@@ -57271,6 +57984,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_ia64 linux-2.6.18-xe
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
++# CONFIG_SFC is not set
+
+#
+# Token Ring devices
@@ -58290,6 +59004,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_ia64 linux-2.6.18-xe
+CONFIG_XEN_BLKDEV_TAP=y
+CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
+# CONFIG_XEN_NETDEV_LOOPBACK is not set
+CONFIG_XEN_PCIDEV_BACKEND=y
+# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
@@ -58298,9 +59014,12 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_ia64 linux-2.6.18-xe
+CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER=y
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
+CONFIG_XEN_TPMDEV_BACKEND=m
++CONFIG_XEN_SCSI_BACKEND=m
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
++CONFIG_XEN_SCSI_FRONTEND=m
+CONFIG_XEN_GRANT_DEV=y
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_SCRUB_PAGES is not set
@@ -58315,10 +59034,10 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_ia64 linux-2.6.18-xe
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_XENCOMM=y
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen0_x86_32
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen0_x86_32 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,1451 @@
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen0_x86_32
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen0_x86_32 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1458 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
@@ -58569,6 +59288,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+# CONFIG_PCIEPORTBUS is not set
++# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+# CONFIG_SCx200 is not set
@@ -59073,6 +59793,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
++# CONFIG_SFC is not set
+
+#
+# Token Ring devices
@@ -59713,7 +60434,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+CONFIG_XEN=y
-+CONFIG_XEN_INTERFACE_VERSION=0x00030206
++CONFIG_XEN_INTERFACE_VERSION=0x00030207
+
+#
+# XEN
@@ -59727,6 +60448,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-
+CONFIG_XEN_BLKDEV_TAP=y
+CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
+# CONFIG_XEN_NETDEV_LOOPBACK is not set
+CONFIG_XEN_PCIDEV_BACKEND=y
+# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
@@ -59735,8 +60458,12 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-
+# CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
+CONFIG_XEN_TPMDEV_BACKEND=m
++CONFIG_XEN_SCSI_BACKEND=m
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
++CONFIG_XEN_SCSI_FRONTEND=m
++CONFIG_XEN_GRANT_DEV=y
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
@@ -59750,7 +60477,6 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-
+CONFIG_XEN_SMPBOOT=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
-+CONFIG_XEN_GRANT_DEV=y
+
+#
+# Library routines
@@ -59770,14 +60496,14 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_32 linux-2.6.18-
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
+CONFIG_KTIME_SCALAR=y
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen0_x86_64
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen0_x86_64 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,1389 @@
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen0_x86_64
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen0_x86_64 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1390 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
-+# Tue Oct 16 09:32:39 2007
++# Mon Feb 18 10:41:04 2008
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
@@ -59802,7 +60528,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
-+CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
@@ -59817,6 +60543,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
++# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -59850,6 +60577,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
++CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
@@ -59887,16 +60615,17 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_X86_GOOD_APIC=y
+CONFIG_MICROCODE=y
-+# CONFIG_X86_MSR is not set
-+# CONFIG_X86_CPUID is not set
++CONFIG_X86_MSR=y
++CONFIG_X86_CPUID=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_XEN_GENAPIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_MTRR=y
-+# CONFIG_SMP is not set
++CONFIG_SMP=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
++CONFIG_PREEMPT_BKL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
@@ -59907,6 +60636,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
++CONFIG_NR_CPUS=8
++CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_SWIOTLB=y
+CONFIG_KEXEC=y
@@ -59918,10 +60649,10 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_REORDER is not set
-+CONFIG_K8_NB=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
++CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# Power management options
@@ -59930,6 +60661,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
++CONFIG_SUSPEND_SMP=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
@@ -59942,20 +60674,22 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
-+# CONFIG_ACPI_HOTKEY is not set
++CONFIG_ACPI_HOTKEY=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=m
++CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
++# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
-+# CONFIG_ACPI_CONTAINER is not set
++CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_PV_SLEEP=y
+
+#
@@ -59968,10 +60702,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
-+# CONFIG_PCI_MMCONFIG is not set
++CONFIG_PCI_MMCONFIG=y
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+# CONFIG_PCIEPORTBUS is not set
++# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
@@ -59988,9 +60723,9 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=y
++# CONFIG_BINFMT_MISC is not set
+CONFIG_IA32_EMULATION=y
-+# CONFIG_IA32_AOUT is not set
++CONFIG_IA32_AOUT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+
@@ -60006,6 +60741,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
@@ -60024,8 +60761,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
-+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
@@ -60119,8 +60856,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+# Generic Driver Options
+#
-+CONFIG_STANDALONE=y
-+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
++# CONFIG_STANDALONE is not set
++CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
@@ -60168,7 +60905,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
-+CONFIG_BLK_DEV_RAM_SIZE=16384
++CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
@@ -60267,7 +61004,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
-+CONFIG_SCSI_ISCSI_ATTRS=y
++# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
@@ -60281,7 +61018,6 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_SCSI_AIC7XXX=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
@@ -60289,7 +61025,6 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_SCSI_AIC79XX=y
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
-+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
@@ -60316,8 +61051,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
-+CONFIG_SCSI_BUSLOGIC=y
-+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
++# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -60339,21 +61073,19 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
-+CONFIG_MD_LINEAR=y
++# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
-+CONFIG_MD_RAID456=y
-+# CONFIG_MD_RAID5_RESHAPE is not set
-+CONFIG_MD_MULTIPATH=y
++# CONFIG_MD_RAID456 is not set
++# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
-+CONFIG_DM_CRYPT=y
++# CONFIG_DM_CRYPT is not set
+CONFIG_DM_SNAPSHOT=y
+CONFIG_DM_MIRROR=y
+# CONFIG_DM_ZERO is not set
-+CONFIG_DM_MULTIPATH=y
-+CONFIG_DM_MULTIPATH_EMC=y
++# CONFIG_DM_MULTIPATH is not set
+
+#
+# Fusion MPT device support
@@ -60474,6 +61206,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
++# CONFIG_SFC is not set
+
+#
+# Token Ring devices
@@ -60561,7 +61294,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
-+# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
@@ -60587,7 +61320,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
-+CONFIG_RTC=y
++# CONFIG_RTC is not set
++# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
@@ -60595,16 +61329,18 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+# Ftape, the floppy tape device driver
+#
-+# CONFIG_FTAPE is not set
+CONFIG_AGP=m
-+CONFIG_AGP_AMD64=m
-+# CONFIG_AGP_INTEL is not set
++# CONFIG_AGP_AMD64 is not set
++CONFIG_AGP_INTEL=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_VIA=m
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
++CONFIG_DRM_I810=m
++CONFIG_DRM_I830=m
++CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+# CONFIG_DRM_VIA is not set
@@ -60803,8 +61539,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+# LED devices
+#
-+CONFIG_NEW_LEDS=y
-+CONFIG_LEDS_CLASS=m
++# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
@@ -60813,25 +61548,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+# LED Triggers
+#
-+CONFIG_LEDS_TRIGGERS=y
-+CONFIG_LEDS_TRIGGER_TIMER=y
-+CONFIG_LEDS_TRIGGER_IDE_DISK=y
-+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+
+#
+# InfiniBand support
+#
-+CONFIG_INFINIBAND=y
-+# CONFIG_INFINIBAND_USER_MAD is not set
-+# CONFIG_INFINIBAND_USER_ACCESS is not set
-+CONFIG_INFINIBAND_ADDR_TRANS=y
-+CONFIG_INFINIBAND_MTHCA=y
-+CONFIG_INFINIBAND_MTHCA_DEBUG=y
-+CONFIG_INFINIBAND_IPOIB=y
-+CONFIG_INFINIBAND_IPOIB_DEBUG=y
-+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
-+CONFIG_INFINIBAND_SRP=y
-+CONFIG_INFINIBAND_ISER=y
++# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -60855,11 +61576,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+# RTC drivers
+#
-+CONFIG_RTC_DRV_DS1553=m
-+CONFIG_RTC_DRV_DS1742=m
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_TEST=m
-+CONFIG_RTC_DRV_V3020=m
++# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# DMA Engine support
@@ -60924,9 +61645,9 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+#
+# DOS/FAT/NT Filesystems
+#
-+CONFIG_FAT_FS=y
-+CONFIG_MSDOS_FS=y
-+CONFIG_VFAT_FS=y
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
@@ -61051,7 +61772,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_KERNEL=y
-+CONFIG_LOG_BUF_SHIFT=15
++CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
@@ -61065,7 +61786,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
-+# CONFIG_DEBUG_INFO is not set
++CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
@@ -61116,7 +61837,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# Hardware crypto devices
+#
+CONFIG_XEN=y
-+CONFIG_XEN_INTERFACE_VERSION=0x00030206
++CONFIG_XEN_INTERFACE_VERSION=0x00030207
+
+#
+# XEN
@@ -61130,6 +61851,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_XEN_BLKDEV_TAP=y
+CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
+# CONFIG_XEN_NETDEV_LOOPBACK is not set
+CONFIG_XEN_PCIDEV_BACKEND=y
+# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
@@ -61137,9 +61860,13 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
+# CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
-+CONFIG_XEN_TPMDEV_BACKEND=m
++# CONFIG_XEN_TPMDEV_BACKEND is not set
++# CONFIG_XEN_SCSI_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
++CONFIG_XEN_SCSI_FRONTEND=m
++CONFIG_XEN_GRANT_DEV=y
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
@@ -61150,9 +61877,9 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+CONFIG_XEN_COMPAT=0x030002
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
++CONFIG_XEN_SMPBOOT=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
-+CONFIG_XEN_GRANT_DEV=y
+
+#
+# Library routines
@@ -61160,17 +61887,17 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen0_x86_64 linux-2.6.18-
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
-+CONFIG_LIBCRC32C=m
++CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xenU_ia64
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xenU_ia64 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,1507 @@
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen_ia64
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen_ia64 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1703 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
-+# Mon Dec 17 13:38:36 2007
++# Tue Feb 19 11:20:00 2008
+#
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
@@ -61188,12 +61915,13 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
-+# CONFIG_POSIX_MQUEUE is not set
++CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
-+# CONFIG_IKCONFIG is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
@@ -61201,8 +61929,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=y
+CONFIG_KALLSYMS=y
-+# CONFIG_KALLSYMS_ALL is not set
-+# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -61222,10 +61950,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# Loadable module support
+#
+CONFIG_MODULES=y
-+# CONFIG_MODULE_UNLOAD is not set
-+# CONFIG_MODVERSIONS is not set
-+# CONFIG_MODULE_SRCVERSION_ALL is not set
-+# CONFIG_KMOD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
@@ -61266,13 +61995,13 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_IS_DMA32=y
+CONFIG_AUDIT_ARCH=y
-+# CONFIG_IA64_GENERIC is not set
++CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
-+CONFIG_IA64_XEN=y
++# CONFIG_IA64_XEN is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
@@ -61286,8 +62015,9 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_IA64_L1_CACHE_SHIFT=7
-+# CONFIG_IA64_CYCLONE is not set
++CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
++# CONFIG_IA64_SGI_SN_XP is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
@@ -61297,26 +62027,38 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_PERMIT_BSP_REMOVE is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
-+CONFIG_FLATMEM_MANUAL=y
-+# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_FLATMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
-+CONFIG_FLATMEM=y
++CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_MIGRATION is not set
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
++CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
++CONFIG_NUMA=y
++CONFIG_NODES_SHIFT=10
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_HOLES_IN_ZONE=y
++CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
++CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y
+# CONFIG_IA32_SUPPORT is not set
-+CONFIG_IA64_MCA_RECOVERY=y
++# CONFIG_IA64_MCA_RECOVERY is not set
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
-+# CONFIG_KEXEC is not set
-+# CONFIG_CRASH_DUMP is not set
++CONFIG_SGI_SN=y
++
++#
++# SN Devices
++#
++# CONFIG_SGI_IOC3 is not set
++CONFIG_KEXEC=y
+
+#
+# Firmware Drivers
@@ -61343,6 +62085,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
++CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
@@ -61374,6 +62117,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
++# CONFIG_HOTPLUG_PCI_SGI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
@@ -61406,8 +62150,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_SYN_COOKIES is not set
++CONFIG_ARPD=y
++CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
@@ -61430,6 +62174,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
@@ -61445,6 +62190,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_IP_NF_QUEUE is not set
+
+#
++# Bridge: Netfilter Configuration
++#
++# CONFIG_BRIDGE_NF_EBTABLES is not set
++
++#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
@@ -61459,9 +62209,10 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
-+# CONFIG_BRIDGE is not set
++CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
++CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
@@ -61493,7 +62244,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
-+# CONFIG_FW_LOADER is not set
++CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
+
@@ -61521,13 +62272,14 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
++CONFIG_BLK_CPQ_CISS_DA=y
++# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
-+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_CRYPTOLOOP=y
++CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
@@ -61541,7 +62293,61 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+# ATA/ATAPI/MFM/RLL support
+#
-+# CONFIG_IDE is not set
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++CONFIG_BLK_DEV_IDECD=y
++# CONFIG_BLK_DEV_IDETAPE is not set
++CONFIG_BLK_DEV_IDEFLOPPY=y
++CONFIG_BLK_DEV_IDESCSI=y
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++# CONFIG_IDE_GENERIC is not set
++CONFIG_BLK_DEV_IDEPCI=y
++# CONFIG_IDEPCI_SHARE_IRQ is not set
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
++CONFIG_IDEDMA_PCI_AUTO=y
++# CONFIG_IDEDMA_ONLYDISK is not set
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++CONFIG_BLK_DEV_CMD64X=y
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++CONFIG_BLK_DEV_PIIX=y
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++# CONFIG_BLK_DEV_VIA82CXXX is not set
++# CONFIG_IDE_ARM is not set
++CONFIG_BLK_DEV_IDEDMA=y
++# CONFIG_IDEDMA_IVB is not set
++CONFIG_IDEDMA_AUTO=y
++# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
@@ -61572,7 +62378,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
-+# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=y
+
@@ -61613,7 +62419,15 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+# Multi-device support (RAID and LVM)
+#
-+# CONFIG_MD is not set
++CONFIG_MD=y
++# CONFIG_BLK_DEV_MD is not set
++CONFIG_BLK_DEV_DM=y
++CONFIG_DM_CRYPT=m
++CONFIG_DM_SNAPSHOT=y
++CONFIG_DM_MIRROR=m
++CONFIG_DM_ZERO=m
++CONFIG_DM_MULTIPATH=m
++CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
@@ -61642,12 +62456,20 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
++CONFIG_TUN=y
+
+#
+# ARCnet devices
+#
-+# CONFIG_ARCNET is not set
++CONFIG_ARCNET=y
++# CONFIG_ARCNET_1201 is not set
++# CONFIG_ARCNET_1051 is not set
++# CONFIG_ARCNET_RAW is not set
++# CONFIG_ARCNET_CAP is not set
++# CONFIG_ARCNET_COM90xx is not set
++# CONFIG_ARCNET_COM90xxIO is not set
++# CONFIG_ARCNET_RIM_I is not set
++# CONFIG_ARCNET_COM20020 is not set
+
+#
+# PHY device support
@@ -61686,7 +62508,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
-+# CONFIG_EEPRO100 is not set
++CONFIG_EEPRO100=y
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
@@ -61725,6 +62547,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
++# CONFIG_SFC is not set
+
+#
+# Token Ring devices
@@ -61746,14 +62569,26 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
-+# CONFIG_NETCONSOLE is not set
-+# CONFIG_NETPOLL is not set
-+# CONFIG_NET_POLL_CONTROLLER is not set
++CONFIG_NETCONSOLE=y
++CONFIG_NETPOLL=y
++# CONFIG_NETPOLL_RX is not set
++# CONFIG_NETPOLL_TRAP is not set
++CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
-+# CONFIG_ISDN is not set
++CONFIG_ISDN=m
++
++#
++# Old ISDN4Linux
++#
++# CONFIG_ISDN_I4L is not set
++
++#
++# CAPI subsystem
++#
++# CONFIG_ISDN_CAPI is not set
+
+#
+# Telephony Support
@@ -61780,8 +62615,16 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+# Input Device Drivers
+#
-+# CONFIG_INPUT_KEYBOARD is not set
-+# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
@@ -61790,11 +62633,16 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
-+# CONFIG_SERIO_I8042 is not set
++CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
-+# CONFIG_GAMEPORT is not set
++CONFIG_GAMEPORT=y
++# CONFIG_GAMEPORT_NS558 is not set
++# CONFIG_GAMEPORT_L4 is not set
++# CONFIG_GAMEPORT_EMU10K1 is not set
++# CONFIG_GAMEPORT_FM801 is not set
+
+#
+# Character devices
@@ -61803,26 +62651,32 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_COMPUTONE is not set
++# CONFIG_ROCKETPORT is not set
++# CONFIG_CYCLADES is not set
++# CONFIG_DIGIEPCA is not set
++# CONFIG_MOXA_INTELLIO is not set
++# CONFIG_MOXA_SMARTIO is not set
++# CONFIG_ISI is not set
++# CONFIG_SYNCLINKMP is not set
++# CONFIG_SYNCLINK_GT is not set
++# CONFIG_N_HDLC is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_SX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++# CONFIG_SGI_SNSC is not set
++# CONFIG_SGI_TIOCX is not set
+
+#
+# Serial drivers
+#
-+CONFIG_SERIAL_8250=y
-+CONFIG_SERIAL_8250_CONSOLE=y
-+CONFIG_SERIAL_8250_PCI=y
-+CONFIG_SERIAL_8250_NR_UARTS=8
-+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-+CONFIG_SERIAL_8250_EXTENDED=y
-+CONFIG_SERIAL_8250_SHARE_IRQ=y
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
-+CONFIG_SERIAL_CORE=y
-+CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_SGI_L1_CONSOLE is not set
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
@@ -61849,10 +62703,13 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_AGP=y
+# CONFIG_AGP_SIS is not set
+# CONFIG_AGP_VIA is not set
++CONFIG_AGP_I460=y
++# CONFIG_AGP_HP_ZX1 is not set
++# CONFIG_AGP_SGI_TIOCA is not set
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_R128 is not set
-+CONFIG_DRM_RADEON=y
++# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_DRM_VIA is not set
@@ -61860,6 +62717,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
++# CONFIG_MMTIMER is not set
+
+#
+# TPM devices
@@ -62128,7 +62986,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=y
-+# CONFIG_SND_SEQ_DUMMY is not set
++CONFIG_SND_SEQ_DUMMY=y
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
@@ -62147,11 +63005,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_SND_OPL3_LIB=y
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
-+# CONFIG_SND_DUMMY is not set
-+# CONFIG_SND_VIRMIDI is not set
++CONFIG_SND_DUMMY=y
++CONFIG_SND_VIRMIDI=y
+# CONFIG_SND_MTPAV is not set
-+# CONFIG_SND_SERIAL_U16550 is not set
-+# CONFIG_SND_MPU401 is not set
++CONFIG_SND_SERIAL_U16550=y
++CONFIG_SND_MPU401=y
+
+#
+# PCI devices
@@ -62159,7 +63017,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
-+# CONFIG_SND_ATIIXP is not set
++CONFIG_SND_ATIIXP=y
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
@@ -62170,6 +63028,18 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
++# CONFIG_SND_DARLA20 is not set
++# CONFIG_SND_GINA20 is not set
++# CONFIG_SND_LAYLA20 is not set
++# CONFIG_SND_DARLA24 is not set
++# CONFIG_SND_GINA24 is not set
++# CONFIG_SND_LAYLA24 is not set
++# CONFIG_SND_MONA is not set
++# CONFIG_SND_MIA is not set
++# CONFIG_SND_ECHO3G is not set
++# CONFIG_SND_INDIGO is not set
++# CONFIG_SND_INDIGOIO is not set
++# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
@@ -62190,6 +63060,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
++# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
@@ -62208,7 +63079,16 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+# Open Sound System
+#
-+# CONFIG_SOUND_PRIME is not set
++CONFIG_SOUND_PRIME=y
++# CONFIG_OSS_OBSOLETE_DRIVER is not set
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_ES1371 is not set
++# CONFIG_SOUND_ICH is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_VIA82CXXX is not set
++# CONFIG_SOUND_TVMIXER is not set
+
+#
+# USB support
@@ -62222,7 +63102,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+# Miscellaneous USB options
+#
-+# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICEFS=y
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
@@ -62259,6 +63139,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
@@ -62331,6 +63212,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
++# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
@@ -62391,20 +63273,29 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
-+# CONFIG_EXT2_FS_POSIX_ACL is not set
-+# CONFIG_EXT2_FS_SECURITY is not set
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_POSIX_ACL is not set
-+# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_EXT3_FS_POSIX_ACL=y
++CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
-+# CONFIG_REISERFS_FS is not set
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++CONFIG_REISERFS_FS_XATTR=y
++CONFIG_REISERFS_FS_POSIX_ACL=y
++CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
-+# CONFIG_FS_POSIX_ACL is not set
-+# CONFIG_XFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_XFS_FS=y
++# CONFIG_XFS_QUOTA is not set
++# CONFIG_XFS_SECURITY is not set
++# CONFIG_XFS_POSIX_ACL is not set
++# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
@@ -62413,7 +63304,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
-+# CONFIG_AUTOFS4_FS is not set
++CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
@@ -62440,6 +63331,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
++CONFIG_PROC_IOMEM_MACHINE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
@@ -62470,12 +63362,12 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
-+# CONFIG_NFS_DIRECTIO is not set
++CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
-+# CONFIG_NFSD_V4 is not set
-+# CONFIG_NFSD_TCP is not set
++CONFIG_NFSD_V4=y
++CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
@@ -62485,8 +63377,15 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
-+# CONFIG_SMB_FS is not set
-+# CONFIG_CIFS is not set
++CONFIG_SMB_FS=y
++CONFIG_SMB_NLS_DEFAULT=y
++CONFIG_SMB_NLS_REMOTE="cp437"
++CONFIG_CIFS=y
++# CONFIG_CIFS_STATS is not set
++# CONFIG_CIFS_WEAK_PW_HASH is not set
++# CONFIG_CIFS_XATTR is not set
++# CONFIG_CIFS_DEBUG2 is not set
++# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
@@ -62507,7 +63406,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
-+# CONFIG_SGI_PARTITION is not set
++CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
@@ -62571,6 +63470,13 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_IRQ_PER_CPU=y
+
+#
++# HP Simulator drivers
++#
++# CONFIG_HP_SIMETH is not set
++# CONFIG_HP_SIMSERIAL is not set
++# CONFIG_HP_SIMSCSI is not set
++
++#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
@@ -62583,7 +63489,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_KERNEL=y
-+CONFIG_LOG_BUF_SHIFT=17
++CONFIG_LOG_BUF_SHIFT=20
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
@@ -62652,18 +63558,35 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+#
+# XEN
+#
-+# CONFIG_XEN_PRIVILEGED_GUEST is not set
-+CONFIG_XEN_UNPRIVILEGED_GUEST=y
++CONFIG_XEN_PRIVILEGED_GUEST=y
++# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
-+# CONFIG_XEN_BACKEND is not set
++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_ACCEL_SFC_UTIL is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
++# CONFIG_XEN_NETDEV_LOOPBACK is not set
++CONFIG_XEN_PCIDEV_BACKEND=y
++# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
++# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
++# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
++CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER=y
++# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
++CONFIG_XEN_TPMDEV_BACKEND=m
++CONFIG_XEN_SCSI_BACKEND=m
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
-+# CONFIG_XEN_GRANT_DEV is not set
++CONFIG_XEN_SCSI_FRONTEND=m
++CONFIG_XEN_GRANT_DEV=y
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_SCRUB_PAGES is not set
-+# CONFIG_XEN_DISABLE_SERIAL is not set
++CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_030004_AND_LATER is not set
@@ -62674,26 +63597,15 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xe
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_XENCOMM=y
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xenU_x86_32
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xenU_x86_32 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,950 @@
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xenU_ia64
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_ia64 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xenU_ia64 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1511 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
-+# Tue Oct 16 09:31:29 2007
++# Tue Feb 19 11:20:14 2008
+#
-+CONFIG_X86_32=y
-+CONFIG_LOCKDEP_SUPPORT=y
-+CONFIG_STACKTRACE_SUPPORT=y
-+CONFIG_SEMAPHORE_SLEEPERS=y
-+CONFIG_X86=y
-+CONFIG_MMU=y
-+CONFIG_GENERIC_ISA_DMA=y
-+CONFIG_GENERIC_IOMAP=y
-+CONFIG_GENERIC_HWEIGHT=y
-+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
@@ -62707,20 +63619,20 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# General setup
+#
+CONFIG_LOCALVERSION=""
-+# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
-+# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
-+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
-+CONFIG_UID16=y
+CONFIG_SYSCTL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
@@ -62744,19 +63656,16 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# Loadable module support
+#
+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=y
-+# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
-+CONFIG_KMOD=y
++# CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
-+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
-+CONFIG_LSF=y
+
+#
+# IO Schedulers
@@ -62774,77 +63683,53 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# Processor type and features
+#
-+CONFIG_SMP=y
-+# CONFIG_X86_PC is not set
-+CONFIG_X86_XEN=y
-+# CONFIG_X86_ELAN is not set
-+# CONFIG_X86_VOYAGER is not set
-+# CONFIG_X86_NUMAQ is not set
-+# CONFIG_X86_SUMMIT is not set
-+# CONFIG_X86_BIGSMP is not set
-+# CONFIG_X86_VISWS is not set
-+# CONFIG_X86_GENERICARCH is not set
-+# CONFIG_X86_ES7000 is not set
-+# CONFIG_M386 is not set
-+# CONFIG_M486 is not set
-+# CONFIG_M586 is not set
-+# CONFIG_M586TSC is not set
-+# CONFIG_M586MMX is not set
-+CONFIG_M686=y
-+# CONFIG_MPENTIUMII is not set
-+# CONFIG_MPENTIUMIII is not set
-+# CONFIG_MPENTIUMM is not set
-+# CONFIG_MPENTIUM4 is not set
-+# CONFIG_MK6 is not set
-+# CONFIG_MK7 is not set
-+# CONFIG_MK8 is not set
-+# CONFIG_MCRUSOE is not set
-+# CONFIG_MEFFICEON is not set
-+# CONFIG_MWINCHIPC6 is not set
-+# CONFIG_MWINCHIP2 is not set
-+# CONFIG_MWINCHIP3D is not set
-+# CONFIG_MGEODEGX1 is not set
-+# CONFIG_MGEODE_LX is not set
-+# CONFIG_MCYRIXIII is not set
-+# CONFIG_MVIAC3_2 is not set
-+# CONFIG_X86_GENERIC is not set
-+CONFIG_X86_CMPXCHG=y
-+CONFIG_X86_XADD=y
-+CONFIG_X86_L1_CACHE_SHIFT=5
++CONFIG_IA64=y
++CONFIG_64BIT=y
++CONFIG_MMU=y
++CONFIG_SWIOTLB=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
-+CONFIG_X86_PPRO_FENCE=y
-+CONFIG_X86_WP_WORKS_OK=y
-+CONFIG_X86_INVLPG=y
-+CONFIG_X86_BSWAP=y
-+CONFIG_X86_POPAD_OK=y
-+CONFIG_X86_CMPXCHG64=y
-+CONFIG_X86_GOOD_APIC=y
-+CONFIG_X86_USE_PPRO_CHECKSUM=y
-+CONFIG_NR_CPUS=8
-+CONFIG_PREEMPT_NONE=y
-+# CONFIG_PREEMPT_VOLUNTARY is not set
++CONFIG_TIME_INTERPOLATION=y
++CONFIG_DMI=y
++CONFIG_EFI=y
++CONFIG_GENERIC_IOMAP=y
++CONFIG_XEN=y
++CONFIG_XEN_IA64_EXPOSE_P2M=y
++CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_DMA_IS_DMA32=y
++CONFIG_AUDIT_ARCH=y
++# CONFIG_IA64_GENERIC is not set
++# CONFIG_IA64_DIG is not set
++# CONFIG_IA64_HP_ZX1 is not set
++# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
++# CONFIG_IA64_SGI_SN2 is not set
++# CONFIG_IA64_HP_SIM is not set
++CONFIG_IA64_XEN=y
++# CONFIG_ITANIUM is not set
++CONFIG_MCKINLEY=y
++# CONFIG_IA64_PAGE_SIZE_4KB is not set
++# CONFIG_IA64_PAGE_SIZE_8KB is not set
++CONFIG_IA64_PAGE_SIZE_16KB=y
++# CONFIG_IA64_PAGE_SIZE_64KB is not set
++CONFIG_PGTABLE_3=y
++# CONFIG_PGTABLE_4 is not set
++CONFIG_HZ_100=y
++# CONFIG_HZ_250 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=100
++CONFIG_IA64_L1_CACHE_SHIFT=7
++# CONFIG_IA64_CYCLONE is not set
++CONFIG_IOSAPIC=y
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_SMP=y
++CONFIG_NR_CPUS=16
++CONFIG_HOTPLUG_CPU=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++# CONFIG_SCHED_SMT is not set
++# CONFIG_PERMIT_BSP_REMOVE is not set
+# CONFIG_PREEMPT is not set
-+CONFIG_PREEMPT_BKL=y
-+CONFIG_VM86=y
-+# CONFIG_TOSHIBA is not set
-+# CONFIG_I8K is not set
-+# CONFIG_X86_REBOOTFIXUPS is not set
-+# CONFIG_X86_MSR is not set
-+CONFIG_X86_CPUID=y
-+CONFIG_SWIOTLB=y
-+
-+#
-+# Firmware Drivers
-+#
-+# CONFIG_EDD is not set
-+# CONFIG_DELL_RBU is not set
-+# CONFIG_DCDBAS is not set
-+# CONFIG_NOHIGHMEM is not set
-+CONFIG_HIGHMEM4G=y
-+# CONFIG_HIGHMEM64G is not set
-+CONFIG_PAGE_OFFSET=0xC0000000
-+CONFIG_HIGHMEM=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -62854,40 +63739,80 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
-+# CONFIG_HIGHPTE is not set
-+# CONFIG_REGPARM is not set
-+CONFIG_SECCOMP=y
-+CONFIG_HZ_100=y
-+# CONFIG_HZ_250 is not set
-+# CONFIG_HZ_1000 is not set
-+CONFIG_HZ=100
++CONFIG_ARCH_SELECT_MEMORY_MODEL=y
++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_SPARSEMEM_ENABLE=y
++CONFIG_VIRTUAL_MEM_MAP=y
++CONFIG_HOLES_IN_ZONE=y
++# CONFIG_IA32_SUPPORT is not set
++CONFIG_IA64_MCA_RECOVERY=y
++CONFIG_PERFMON=y
++CONFIG_IA64_PALINFO=y
++# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
-+CONFIG_PHYSICAL_START=0x100000
-+CONFIG_HOTPLUG_CPU=y
-+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
-+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++# Firmware Drivers
+#
-+# CONFIG_PCI is not set
-+CONFIG_ISA_DMA_API=y
-+# CONFIG_SCx200 is not set
++CONFIG_EFI_VARS=y
++CONFIG_EFI_PCDP=y
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
+
+#
-+# PCCARD (PCMCIA/CardBus) support
++# Power management and ACPI
+#
-+# CONFIG_PCCARD is not set
++CONFIG_PM=y
++CONFIG_PM_LEGACY=y
++# CONFIG_PM_DEBUG is not set
++
++#
++# ACPI (Advanced Configuration and Power Interface) Support
++#
++CONFIG_ACPI=y
++CONFIG_ACPI_BUTTON=y
++CONFIG_ACPI_FAN=y
++# CONFIG_ACPI_DOCK is not set
++CONFIG_ACPI_PROCESSOR=y
++CONFIG_ACPI_HOTPLUG_CPU=y
++CONFIG_ACPI_THERMAL=y
++CONFIG_ACPI_BLACKLIST_YEAR=0
++# CONFIG_ACPI_DEBUG is not set
++CONFIG_ACPI_EC=y
++CONFIG_ACPI_POWER=y
++CONFIG_ACPI_SYSTEM=y
++CONFIG_ACPI_CONTAINER=y
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Bus options (PCI, PCMCIA)
++#
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_XEN_PCIDEV_FRONTEND=y
++# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
++# CONFIG_PCIEPORTBUS is not set
++# CONFIG_PCI_DEBUG is not set
+
+#
+# PCI Hotplug Support
+#
++CONFIG_HOTPLUG_PCI=y
++# CONFIG_HOTPLUG_PCI_FAKE is not set
++CONFIG_HOTPLUG_PCI_ACPI=y
++# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
++# CONFIG_HOTPLUG_PCI_CPCI is not set
++# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
-+# Executable file formats
++# PCCARD (PCMCIA/CardBus) support
+#
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_AOUT is not set
-+# CONFIG_BINFMT_MISC is not set
++# CONFIG_PCCARD is not set
+
+#
+# Networking
@@ -62905,15 +63830,16 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
++CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
-+# CONFIG_IP_PNP_DHCP is not set
++CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
@@ -62923,14 +63849,34 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
-+# CONFIG_INET_DIAG is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
++
++#
++# IP: Virtual Server Configuration
++#
++# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
-+# CONFIG_NETFILTER is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_XTABLES is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_CONNTRACK is not set
++# CONFIG_IP_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
@@ -63003,15 +63949,21 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# Plug and Play support
+#
++# CONFIG_PNP is not set
+
+#
+# Block devices
+#
-+# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
-+CONFIG_BLK_DEV_LOOP=m
++CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-+CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
@@ -63029,39 +63981,67 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
-+CONFIG_SCSI=m
++CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
-+CONFIG_BLK_DEV_SD=m
-+# CONFIG_CHR_DEV_ST is not set
-+# CONFIG_CHR_DEV_OSST is not set
-+# CONFIG_BLK_DEV_SR is not set
-+# CONFIG_CHR_DEV_SG is not set
++CONFIG_BLK_DEV_SD=y
++CONFIG_CHR_DEV_ST=y
++CONFIG_CHR_DEV_OSST=y
++CONFIG_BLK_DEV_SR=y
++CONFIG_BLK_DEV_SR_VENDOR=y
++CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
-+# CONFIG_SCSI_MULTI_LUN is not set
-+# CONFIG_SCSI_CONSTANTS is not set
-+# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_MULTI_LUN=y
++CONFIG_SCSI_CONSTANTS=y
++CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
-+# CONFIG_SCSI_SPI_ATTRS is not set
++CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
-+# CONFIG_SCSI_SAS_ATTRS is not set
++CONFIG_SCSI_SAS_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++CONFIG_SCSI_SYM53C8XX_2=y
++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
++CONFIG_SCSI_SYM53C8XX_MMIO=y
++# CONFIG_SCSI_IPR is not set
++CONFIG_SCSI_QLOGIC_1280=y
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
@@ -63072,45 +64052,119 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# Fusion MPT device support
+#
-+# CONFIG_FUSION is not set
++CONFIG_FUSION=y
++CONFIG_FUSION_SPI=y
++# CONFIG_FUSION_FC is not set
++CONFIG_FUSION_SAS=y
++CONFIG_FUSION_MAX_SGE=128
++# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
++# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
++# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
-+# CONFIG_DUMMY is not set
++CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
++# ARCnet devices
++#
++# CONFIG_ARCNET is not set
++
++#
+# PHY device support
+#
++# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
-+# CONFIG_NET_ETHERNET is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++
++#
++# Tulip family network device support
++#
++CONFIG_NET_TULIP=y
++# CONFIG_DE2104X is not set
++CONFIG_TULIP=y
++CONFIG_TULIP_MWI=y
++CONFIG_TULIP_MMIO=y
++CONFIG_TULIP_NAPI=y
++CONFIG_TULIP_NAPI_HW_MITIGATION=y
++# CONFIG_DE4X5 is not set
++# CONFIG_WINBOND_840 is not set
++# CONFIG_DM9102 is not set
++# CONFIG_ULI526X is not set
++# CONFIG_HP100 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_DGRS is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++# CONFIG_E1000_NAPI is not set
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++CONFIG_TIGON3=y
++# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_SFC is not set
+
+#
+# Token Ring devices
+#
++# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
@@ -63121,8 +64175,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# Wan interfaces
+#
+# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
@@ -63147,23 +64204,18 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
-+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-+# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_JOYDEV=y
+# CONFIG_INPUT_TSDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
++CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
-+CONFIG_INPUT_KEYBOARD=y
-+# CONFIG_KEYBOARD_ATKBD is not set
-+# CONFIG_KEYBOARD_SUNKBD is not set
-+# CONFIG_KEYBOARD_LKKBD is not set
-+# CONFIG_KEYBOARD_XTKBD is not set
-+# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
@@ -63173,9 +64225,9 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
-+CONFIG_SERIO_I8042=y
-+CONFIG_SERIO_SERPORT=y
-+# CONFIG_SERIO_CT82C710 is not set
++# CONFIG_SERIO_I8042 is not set
++# CONFIG_SERIO_SERPORT is not set
++# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
@@ -63191,10 +64243,22 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# Serial drivers
+#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=8
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
@@ -63208,22 +64272,28 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
-+CONFIG_HW_RANDOM=y
-+CONFIG_HW_RANDOM_VIA=y
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_GEN_RTC is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
-+# CONFIG_MWAVE is not set
-+# CONFIG_PC8736x_GPIO is not set
-+# CONFIG_NSC_GPIO is not set
-+# CONFIG_CS5535_GPIO is not set
++CONFIG_AGP=y
++# CONFIG_AGP_SIS is not set
++# CONFIG_AGP_VIA is not set
++CONFIG_DRM=y
++# CONFIG_DRM_TDFX is not set
++# CONFIG_DRM_R128 is not set
++CONFIG_DRM_RADEON=y
++# CONFIG_DRM_MGA is not set
++# CONFIG_DRM_SIS is not set
++# CONFIG_DRM_VIA is not set
++# CONFIG_DRM_SAVAGE is not set
+# CONFIG_RAW_DRIVER is not set
++# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
@@ -63235,7 +64305,55 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# I2C support
+#
-+# CONFIG_I2C is not set
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++CONFIG_I2C_ALGOPCF=y
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
@@ -63250,8 +64368,48 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# Hardware Monitoring support
+#
-+# CONFIG_HWMON is not set
++CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
@@ -63260,18 +64418,115 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# Multimedia devices
+#
-+# CONFIG_VIDEO_DEV is not set
++CONFIG_VIDEO_DEV=y
++CONFIG_VIDEO_V4L1=y
++CONFIG_VIDEO_V4L1_COMPAT=y
++CONFIG_VIDEO_V4L2=y
++
++#
++# Video Capture Adapters
++#
++
++#
++# Video Capture Adapters
++#
++# CONFIG_VIDEO_ADV_DEBUG is not set
++# CONFIG_VIDEO_VIVI is not set
++# CONFIG_VIDEO_BT848 is not set
++# CONFIG_VIDEO_CPIA is not set
++# CONFIG_VIDEO_CPIA2 is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_TUNER_3036 is not set
++# CONFIG_VIDEO_STRADIS is not set
++# CONFIG_VIDEO_ZORAN is not set
++# CONFIG_VIDEO_SAA7134 is not set
++# CONFIG_VIDEO_MXB is not set
++# CONFIG_VIDEO_DPC is not set
++# CONFIG_VIDEO_HEXIUM_ORION is not set
++# CONFIG_VIDEO_HEXIUM_GEMINI is not set
++# CONFIG_VIDEO_CX88 is not set
++
++#
++# Encoders and Decoders
++#
++# CONFIG_VIDEO_MSP3400 is not set
++# CONFIG_VIDEO_CS53L32A is not set
++# CONFIG_VIDEO_TLV320AIC23B is not set
++# CONFIG_VIDEO_WM8775 is not set
++# CONFIG_VIDEO_WM8739 is not set
++# CONFIG_VIDEO_CX2341X is not set
++# CONFIG_VIDEO_CX25840 is not set
++# CONFIG_VIDEO_SAA711X is not set
++# CONFIG_VIDEO_SAA7127 is not set
++# CONFIG_VIDEO_UPD64031A is not set
++# CONFIG_VIDEO_UPD64083 is not set
++
++#
++# V4L USB devices
++#
++# CONFIG_VIDEO_PVRUSB2 is not set
++# CONFIG_VIDEO_EM28XX is not set
++# CONFIG_USB_VICAM is not set
++# CONFIG_USB_IBMCAM is not set
++# CONFIG_USB_KONICAWC is not set
++# CONFIG_USB_QUICKCAM_MESSENGER is not set
++# CONFIG_USB_ET61X251 is not set
++# CONFIG_VIDEO_OVCAMCHIP is not set
++# CONFIG_USB_W9968CF is not set
++# CONFIG_USB_OV511 is not set
++# CONFIG_USB_SE401 is not set
++# CONFIG_USB_SN9C102 is not set
++# CONFIG_USB_STV680 is not set
++# CONFIG_USB_ZC0301 is not set
++# CONFIG_USB_PWC is not set
++
++#
++# Radio Adapters
++#
++# CONFIG_RADIO_GEMTEK_PCI is not set
++# CONFIG_RADIO_MAXIRADIO is not set
++# CONFIG_RADIO_MAESTRO is not set
++# CONFIG_USB_DSBR is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
++# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
-+# CONFIG_FB is not set
++CONFIG_FB=y
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_TILEBLITTING is not set
++# CONFIG_FB_CIRRUS is not set
++# CONFIG_FB_PM2 is not set
++# CONFIG_FB_CYBER2000 is not set
++# CONFIG_FB_ASILIANT is not set
++# CONFIG_FB_IMSTT is not set
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_NVIDIA is not set
++# CONFIG_FB_RIVA is not set
++# CONFIG_FB_MATROX is not set
++# CONFIG_FB_RADEON is not set
++# CONFIG_FB_ATY128 is not set
++# CONFIG_FB_ATY is not set
++# CONFIG_FB_SAVAGE is not set
++# CONFIG_FB_SIS is not set
++# CONFIG_FB_NEOMAGIC is not set
++# CONFIG_FB_KYRO is not set
++# CONFIG_FB_3DFX is not set
++# CONFIG_FB_VOODOO1 is not set
++# CONFIG_FB_TRIDENT is not set
++# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
@@ -63279,25 +64534,244 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++# CONFIG_FONTS is not set
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
-+# CONFIG_SOUND is not set
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++CONFIG_SND_HWDEP=y
++CONFIG_SND_RAWMIDI=y
++CONFIG_SND_SEQUENCER=y
++# CONFIG_SND_SEQ_DUMMY is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_PCM_OSS_PLUGINS=y
++CONFIG_SND_SEQUENCER_OSS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++CONFIG_SND_MPU401_UART=y
++CONFIG_SND_OPL3_LIB=y
++CONFIG_SND_AC97_CODEC=y
++CONFIG_SND_AC97_BUS=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_VIRMIDI is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# PCI devices
++#
++# CONFIG_SND_AD1889 is not set
++# CONFIG_SND_ALS300 is not set
++# CONFIG_SND_ALI5451 is not set
++# CONFIG_SND_ATIIXP is not set
++# CONFIG_SND_ATIIXP_MODEM is not set
++# CONFIG_SND_AU8810 is not set
++# CONFIG_SND_AU8820 is not set
++# CONFIG_SND_AU8830 is not set
++# CONFIG_SND_AZT3328 is not set
++# CONFIG_SND_BT87X is not set
++# CONFIG_SND_CA0106 is not set
++# CONFIG_SND_CMIPCI is not set
++# CONFIG_SND_CS4281 is not set
++# CONFIG_SND_CS46XX is not set
++# CONFIG_SND_EMU10K1 is not set
++# CONFIG_SND_EMU10K1X is not set
++# CONFIG_SND_ENS1370 is not set
++# CONFIG_SND_ENS1371 is not set
++# CONFIG_SND_ES1938 is not set
++# CONFIG_SND_ES1968 is not set
++CONFIG_SND_FM801=y
++# CONFIG_SND_FM801_TEA575X_BOOL is not set
++# CONFIG_SND_HDA_INTEL is not set
++# CONFIG_SND_HDSP is not set
++# CONFIG_SND_HDSPM is not set
++# CONFIG_SND_ICE1712 is not set
++# CONFIG_SND_ICE1724 is not set
++# CONFIG_SND_INTEL8X0 is not set
++# CONFIG_SND_INTEL8X0M is not set
++# CONFIG_SND_KORG1212 is not set
++# CONFIG_SND_MAESTRO3 is not set
++# CONFIG_SND_MIXART is not set
++# CONFIG_SND_NM256 is not set
++# CONFIG_SND_PCXHR is not set
++# CONFIG_SND_RME32 is not set
++# CONFIG_SND_RME96 is not set
++# CONFIG_SND_RME9652 is not set
++# CONFIG_SND_SONICVIBES is not set
++# CONFIG_SND_TRIDENT is not set
++# CONFIG_SND_VIA82XX is not set
++# CONFIG_SND_VIA82XX_MODEM is not set
++# CONFIG_SND_VX222 is not set
++# CONFIG_SND_YMFPCI is not set
++
++#
++# USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
-+# CONFIG_USB_ARCH_HAS_HCD is not set
-+# CONFIG_USB_ARCH_HAS_OHCI is not set
-+# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_BANDWIDTH=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_SPLIT_ISO is not set
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++CONFIG_USB_HIDDEV=y
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_ACECAD is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_TOUCHSCREEN is not set
++# CONFIG_USB_YEALINK is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++# CONFIG_USB_ATI_REMOTE2 is not set
++# CONFIG_USB_KEYSPAN_REMOTE is not set
++# CONFIG_USB_APPLETOUCH is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETKIT is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++
++#
++# USB DSL modem support
++#
++
++#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
@@ -63323,11 +64797,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# InfiniBand support
+#
++# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
-+# CONFIG_EDAC is not set
+
+#
+# Real Time Clock
@@ -63351,7 +64825,9 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# File systems
+#
+CONFIG_EXT2_FS=y
-+# CONFIG_EXT2_FS_XATTR is not set
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
@@ -63360,10 +64836,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
-+CONFIG_REISERFS_FS=y
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
@@ -63375,7 +64848,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
-+CONFIG_AUTOFS4_FS=y
++# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
@@ -63383,16 +64856,16 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
-+CONFIG_ZISOFS=y
-+CONFIG_ZISOFS_FS=y
-+# CONFIG_UDF_FS is not set
++# CONFIG_ZISOFS is not set
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+CONFIG_VFAT_FS=m
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
@@ -63418,7 +64891,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
-+CONFIG_CRAMFS=y
++# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
@@ -63431,15 +64904,21 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
-+# CONFIG_NFS_V4 is not set
++CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
-+# CONFIG_NFSD is not set
++CONFIG_NFSD=y
++CONFIG_NFSD_V3=y
++# CONFIG_NFSD_V3_ACL is not set
++# CONFIG_NFSD_V4 is not set
++# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
-+# CONFIG_RPCSEC_GSS_KRB5 is not set
++CONFIG_SUNRPC_GSS=y
++CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
@@ -63451,8 +64930,23 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# Partition Types
+#
-+# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
@@ -63460,43 +64954,56 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
++CONFIG_NLS_CODEPAGE_737=y
++CONFIG_NLS_CODEPAGE_775=y
++CONFIG_NLS_CODEPAGE_850=y
++CONFIG_NLS_CODEPAGE_852=y
++CONFIG_NLS_CODEPAGE_855=y
++CONFIG_NLS_CODEPAGE_857=y
++CONFIG_NLS_CODEPAGE_860=y
++CONFIG_NLS_CODEPAGE_861=y
++CONFIG_NLS_CODEPAGE_862=y
++CONFIG_NLS_CODEPAGE_863=y
++CONFIG_NLS_CODEPAGE_864=y
++CONFIG_NLS_CODEPAGE_865=y
++CONFIG_NLS_CODEPAGE_866=y
++CONFIG_NLS_CODEPAGE_869=y
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++CONFIG_NLS_CODEPAGE_949=y
++CONFIG_NLS_CODEPAGE_874=y
++CONFIG_NLS_ISO8859_8=y
+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_CODEPAGE_1251=y
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
++CONFIG_NLS_ISO8859_2=y
++CONFIG_NLS_ISO8859_3=y
++CONFIG_NLS_ISO8859_4=y
++CONFIG_NLS_ISO8859_5=y
++CONFIG_NLS_ISO8859_6=y
++CONFIG_NLS_ISO8859_7=y
++CONFIG_NLS_ISO8859_9=y
++CONFIG_NLS_ISO8859_13=y
++CONFIG_NLS_ISO8859_14=y
++CONFIG_NLS_ISO8859_15=y
++CONFIG_NLS_KOI8_R=y
++CONFIG_NLS_KOI8_U=y
++CONFIG_NLS_UTF8=y
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_PENDING_IRQ=y
++CONFIG_IRQ_PER_CPU=y
+
+#
+# Instrumentation Support
@@ -63507,40 +65014,33 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+#
+# Kernel hacking
+#
-+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_KERNEL=y
-+CONFIG_LOG_BUF_SHIFT=14
++CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_MUTEXES is not set
++CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RWSEMS is not set
-+# CONFIG_DEBUG_LOCK_ALLOC is not set
-+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
-+# CONFIG_DEBUG_HIGHMEM is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
-+CONFIG_FRAME_POINTER=y
-+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
-+CONFIG_EARLY_PRINTK=y
-+# CONFIG_DEBUG_STACKOVERFLOW is not set
-+# CONFIG_DEBUG_STACK_USAGE is not set
-+# CONFIG_DEBUG_PAGEALLOC is not set
-+# CONFIG_DEBUG_RODATA is not set
-+# CONFIG_4KSTACKS is not set
++CONFIG_IA64_GRANULE_16MB=y
++# CONFIG_IA64_GRANULE_64MB is not set
++CONFIG_IA64_PRINT_HAZARDS=y
++# CONFIG_DISABLE_VHPT is not set
++# CONFIG_IA64_DEBUG_CMPXCHG is not set
++# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
@@ -63555,18 +65055,17 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
-+CONFIG_CRYPTO_MD5=m
++CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
-+# CONFIG_CRYPTO_DES is not set
++CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
-+# CONFIG_CRYPTO_AES_586 is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
@@ -63575,15 +65074,15 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
-+CONFIG_CRYPTO_CRC32C=m
++# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
-+# CONFIG_CRYPTO_DEV_PADLOCK is not set
-+CONFIG_XEN=y
-+CONFIG_XEN_INTERFACE_VERSION=0x00030206
++# CONFIG_XEN_SMPBOOT is not set
++# CONFIG_XEN_DEVMEM is not set
++CONFIG_XEN_INTERFACE_VERSION=0x00030207
+
+#
+# XEN
@@ -63593,10 +65092,16 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+# CONFIG_XEN_BACKEND is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
-+CONFIG_XEN_SCRUB_PAGES=y
-+CONFIG_XEN_DISABLE_SERIAL=y
++CONFIG_XEN_SCSI_FRONTEND=m
++# CONFIG_XEN_GRANT_DEV is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
++CONFIG_XEN_FRAMEBUFFER=y
++CONFIG_XEN_KEYBOARD=y
++# CONFIG_XEN_SCRUB_PAGES is not set
++# CONFIG_XEN_DISABLE_SERIAL is not set
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_030004_AND_LATER is not set
@@ -63605,55 +65110,28 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-
+CONFIG_XEN_COMPAT=0x030002
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
-+CONFIG_XEN_SMPBOOT=y
+CONFIG_XEN_BALLOON=y
-+CONFIG_XEN_DEVMEM=y
-+# CONFIG_XEN_GRANT_DEV is not set
-+
-+#
-+# Library routines
-+#
-+# CONFIG_CRC_CCITT is not set
-+# CONFIG_CRC16 is not set
-+# CONFIG_CRC32 is not set
-+CONFIG_LIBCRC32C=m
-+CONFIG_ZLIB_INFLATE=y
-+CONFIG_PLIST=y
-+CONFIG_GENERIC_HARDIRQS=y
-+CONFIG_GENERIC_IRQ_PROBE=y
-+CONFIG_GENERIC_PENDING_IRQ=y
-+CONFIG_X86_SMP=y
-+CONFIG_X86_BIOS_REBOOT=y
-+CONFIG_X86_TRAMPOLINE=y
-+CONFIG_X86_NO_TSS=y
-+CONFIG_X86_NO_IDT=y
-+CONFIG_KTIME_SCALAR=y
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xenU_x86_64
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xenU_x86_64 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,1241 @@
++CONFIG_XEN_XENCOMM=y
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xenU_x86_32
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_32 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xenU_x86_32 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,953 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
-+# Tue Oct 16 09:32:52 2007
++# Tue Oct 16 09:31:29 2007
+#
-+CONFIG_X86_64=y
-+CONFIG_64BIT=y
-+CONFIG_X86=y
++CONFIG_X86_32=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_X86=y
+CONFIG_MMU=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+CONFIG_GENERIC_HWEIGHT=y
-+CONFIG_GENERIC_CALIBRATE_DELAY=y
-+CONFIG_X86_CMPXCHG=y
-+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
++CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
-+CONFIG_AUDIT_ARCH=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
@@ -63670,12 +65148,10 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
-+CONFIG_POSIX_MQUEUE=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
-+CONFIG_AUDIT=y
-+CONFIG_AUDITSYSCALL=y
++# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
@@ -63686,7 +65162,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_SYSCTL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
-+CONFIG_KALLSYMS_EXTRA_PASS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -63708,7 +65184,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
-+CONFIG_MODVERSIONS=y
++# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
@@ -63716,7 +65192,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# Block layer
+#
-+CONFIG_LBD=y
++# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LSF=y
+
@@ -63736,28 +65212,77 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# Processor type and features
+#
-+CONFIG_X86_PC=y
-+# CONFIG_X86_VSMP is not set
++CONFIG_SMP=y
++# CONFIG_X86_PC is not set
++CONFIG_X86_XEN=y
++# CONFIG_X86_ELAN is not set
++# CONFIG_X86_VOYAGER is not set
++# CONFIG_X86_NUMAQ is not set
++# CONFIG_X86_SUMMIT is not set
++# CONFIG_X86_BIGSMP is not set
++# CONFIG_X86_VISWS is not set
++# CONFIG_X86_GENERICARCH is not set
++# CONFIG_X86_ES7000 is not set
++# CONFIG_M386 is not set
++# CONFIG_M486 is not set
++# CONFIG_M586 is not set
++# CONFIG_M586TSC is not set
++# CONFIG_M586MMX is not set
++CONFIG_M686=y
++# CONFIG_MPENTIUMII is not set
++# CONFIG_MPENTIUMIII is not set
++# CONFIG_MPENTIUMM is not set
++# CONFIG_MPENTIUM4 is not set
++# CONFIG_MK6 is not set
++# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
-+CONFIG_MPSC=y
-+# CONFIG_GENERIC_CPU is not set
-+CONFIG_X86_64_XEN=y
-+CONFIG_X86_NO_TSS=y
-+CONFIG_X86_NO_IDT=y
-+CONFIG_X86_L1_CACHE_BYTES=128
-+CONFIG_X86_L1_CACHE_SHIFT=7
-+CONFIG_X86_INTERNODE_CACHE_BYTES=128
++# CONFIG_MCRUSOE is not set
++# CONFIG_MEFFICEON is not set
++# CONFIG_MWINCHIPC6 is not set
++# CONFIG_MWINCHIP2 is not set
++# CONFIG_MWINCHIP3D is not set
++# CONFIG_MGEODEGX1 is not set
++# CONFIG_MGEODE_LX is not set
++# CONFIG_MCYRIXIII is not set
++# CONFIG_MVIAC3_2 is not set
++# CONFIG_X86_GENERIC is not set
++CONFIG_X86_CMPXCHG=y
++CONFIG_X86_XADD=y
++CONFIG_X86_L1_CACHE_SHIFT=5
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_X86_PPRO_FENCE=y
++CONFIG_X86_WP_WORKS_OK=y
++CONFIG_X86_INVLPG=y
++CONFIG_X86_BSWAP=y
++CONFIG_X86_POPAD_OK=y
++CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
-+# CONFIG_MICROCODE is not set
-+# CONFIG_X86_MSR is not set
-+CONFIG_X86_CPUID=y
-+CONFIG_X86_XEN_GENAPIC=y
-+CONFIG_SMP=y
++CONFIG_X86_USE_PPRO_CHECKSUM=y
++CONFIG_NR_CPUS=8
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
-+CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_VM86=y
++# CONFIG_TOSHIBA is not set
++# CONFIG_I8K is not set
++# CONFIG_X86_REBOOTFIXUPS is not set
++# CONFIG_X86_MSR is not set
++CONFIG_X86_CPUID=y
++CONFIG_SWIOTLB=y
++
++#
++# Firmware Drivers
++#
++# CONFIG_EDD is not set
++# CONFIG_DELL_RBU is not set
++# CONFIG_DCDBAS is not set
++# CONFIG_NOHIGHMEM is not set
++CONFIG_HIGHMEM4G=y
++# CONFIG_HIGHMEM64G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++CONFIG_HIGHMEM=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -63767,27 +65292,24 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
-+CONFIG_NR_CPUS=16
-+# CONFIG_HOTPLUG_CPU is not set
-+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-+CONFIG_SWIOTLB=y
-+# CONFIG_CRASH_DUMP is not set
-+CONFIG_PHYSICAL_START=0x200000
++# CONFIG_HIGHPTE is not set
++# CONFIG_REGPARM is not set
+CONFIG_SECCOMP=y
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
-+# CONFIG_REORDER is not set
-+CONFIG_GENERIC_HARDIRQS=y
-+CONFIG_GENERIC_IRQ_PROBE=y
-+CONFIG_ISA_DMA_API=y
-+CONFIG_GENERIC_PENDING_IRQ=y
++# CONFIG_CRASH_DUMP is not set
++CONFIG_PHYSICAL_START=0x100000
++CONFIG_HOTPLUG_CPU=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
-+# Bus options (PCI etc.)
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
++CONFIG_ISA_DMA_API=y
++# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
@@ -63799,14 +65321,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+
+#
-+# Executable file formats / Emulations
++# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=y
-+CONFIG_IA32_EMULATION=y
-+# CONFIG_IA32_AOUT is not set
-+CONFIG_COMPAT=y
-+CONFIG_SYSVIPC_COMPAT=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
@@ -63818,146 +65337,38 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
-+CONFIG_PACKET_MMAP=y
++# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
-+CONFIG_XFRM_USER=y
-+CONFIG_NET_KEY=m
++# CONFIG_XFRM_USER is not set
++# CONFIG_NET_KEY is not set
+CONFIG_INET=y
-+CONFIG_IP_MULTICAST=y
-+CONFIG_IP_ADVANCED_ROUTER=y
-+CONFIG_ASK_IP_FIB_HASH=y
-+# CONFIG_IP_FIB_TRIE is not set
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
-+CONFIG_IP_MULTIPLE_TABLES=y
-+CONFIG_IP_ROUTE_FWMARK=y
-+CONFIG_IP_ROUTE_MULTIPATH=y
-+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
-+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+CONFIG_IP_PNP_RARP=y
-+CONFIG_NET_IPIP=m
-+CONFIG_NET_IPGRE=m
-+CONFIG_NET_IPGRE_BROADCAST=y
-+CONFIG_IP_MROUTE=y
-+CONFIG_IP_PIMSM_V1=y
-+CONFIG_IP_PIMSM_V2=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
-+CONFIG_SYN_COOKIES=y
-+CONFIG_INET_AH=m
-+CONFIG_INET_ESP=m
-+CONFIG_INET_IPCOMP=m
-+CONFIG_INET_XFRM_TUNNEL=m
-+CONFIG_INET_TUNNEL=m
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
-+
-+#
-+# IP: Virtual Server Configuration
-+#
-+CONFIG_IP_VS=m
-+# CONFIG_IP_VS_DEBUG is not set
-+CONFIG_IP_VS_TAB_BITS=12
-+
-+#
-+# IPVS transport protocol load balancing support
-+#
-+CONFIG_IP_VS_PROTO_TCP=y
-+CONFIG_IP_VS_PROTO_UDP=y
-+CONFIG_IP_VS_PROTO_ESP=y
-+CONFIG_IP_VS_PROTO_AH=y
-+
-+#
-+# IPVS scheduler
-+#
-+CONFIG_IP_VS_RR=m
-+CONFIG_IP_VS_WRR=m
-+CONFIG_IP_VS_LC=m
-+CONFIG_IP_VS_WLC=m
-+CONFIG_IP_VS_LBLC=m
-+CONFIG_IP_VS_LBLCR=m
-+CONFIG_IP_VS_DH=m
-+CONFIG_IP_VS_SH=m
-+CONFIG_IP_VS_SED=m
-+CONFIG_IP_VS_NQ=m
-+
-+#
-+# IPVS application helper
-+#
-+CONFIG_IP_VS_FTP=m
-+CONFIG_IPV6=m
-+CONFIG_IPV6_PRIVACY=y
-+# CONFIG_IPV6_ROUTER_PREF is not set
-+CONFIG_INET6_AH=m
-+CONFIG_INET6_ESP=m
-+CONFIG_INET6_IPCOMP=m
-+CONFIG_INET6_XFRM_TUNNEL=m
-+CONFIG_INET6_TUNNEL=m
-+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-+CONFIG_INET6_XFRM_MODE_TUNNEL=m
-+CONFIG_IPV6_TUNNEL=m
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
-+CONFIG_NETFILTER=y
-+# CONFIG_NETFILTER_DEBUG is not set
-+CONFIG_BRIDGE_NETFILTER=y
-+
-+#
-+# Core Netfilter Configuration
-+#
-+# CONFIG_NETFILTER_NETLINK is not set
-+# CONFIG_NETFILTER_XTABLES is not set
-+
-+#
-+# IP: Netfilter Configuration
-+#
-+CONFIG_IP_NF_CONNTRACK=m
-+CONFIG_IP_NF_CT_ACCT=y
-+# CONFIG_IP_NF_CONNTRACK_MARK is not set
-+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-+CONFIG_IP_NF_CT_PROTO_SCTP=m
-+CONFIG_IP_NF_FTP=m
-+CONFIG_IP_NF_IRC=m
-+# CONFIG_IP_NF_NETBIOS_NS is not set
-+CONFIG_IP_NF_TFTP=m
-+CONFIG_IP_NF_AMANDA=m
-+# CONFIG_IP_NF_PPTP is not set
-+# CONFIG_IP_NF_H323 is not set
-+# CONFIG_IP_NF_SIP is not set
-+CONFIG_IP_NF_QUEUE=m
-+
-+#
-+# IPv6: Netfilter Configuration (EXPERIMENTAL)
-+#
-+# CONFIG_IP6_NF_QUEUE is not set
-+
-+#
-+# Bridge: Netfilter Configuration
-+#
-+CONFIG_BRIDGE_NF_EBTABLES=m
-+CONFIG_BRIDGE_EBT_BROUTE=m
-+CONFIG_BRIDGE_EBT_T_FILTER=m
-+CONFIG_BRIDGE_EBT_T_NAT=m
-+CONFIG_BRIDGE_EBT_802_3=m
-+CONFIG_BRIDGE_EBT_AMONG=m
-+CONFIG_BRIDGE_EBT_ARP=m
-+CONFIG_BRIDGE_EBT_IP=m
-+CONFIG_BRIDGE_EBT_LIMIT=m
-+CONFIG_BRIDGE_EBT_MARK=m
-+CONFIG_BRIDGE_EBT_PKTTYPE=m
-+CONFIG_BRIDGE_EBT_STP=m
-+CONFIG_BRIDGE_EBT_VLAN=m
-+CONFIG_BRIDGE_EBT_ARPREPLY=m
-+CONFIG_BRIDGE_EBT_DNAT=m
-+CONFIG_BRIDGE_EBT_MARK_T=m
-+CONFIG_BRIDGE_EBT_REDIRECT=m
-+CONFIG_BRIDGE_EBT_SNAT=m
-+CONFIG_BRIDGE_EBT_LOG=m
-+# CONFIG_BRIDGE_EBT_ULOG is not set
++# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
@@ -63967,167 +65378,37 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
-+CONFIG_IP_SCTP=m
-+# CONFIG_SCTP_DBG_MSG is not set
-+# CONFIG_SCTP_DBG_OBJCNT is not set
-+# CONFIG_SCTP_HMAC_NONE is not set
-+# CONFIG_SCTP_HMAC_SHA1 is not set
-+CONFIG_SCTP_HMAC_MD5=y
++# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
-+CONFIG_ATM=m
-+CONFIG_ATM_CLIP=m
-+# CONFIG_ATM_CLIP_NO_ICMP is not set
-+CONFIG_ATM_LANE=m
-+# CONFIG_ATM_MPOA is not set
-+CONFIG_ATM_BR2684=m
-+# CONFIG_ATM_BR2684_IPFILTER is not set
-+CONFIG_BRIDGE=m
-+CONFIG_VLAN_8021Q=m
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
-+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
-+CONFIG_IPX=m
-+# CONFIG_IPX_INTERN is not set
-+CONFIG_ATALK=m
-+CONFIG_DEV_APPLETALK=m
-+CONFIG_IPDDP=m
-+CONFIG_IPDDP_ENCAP=y
-+CONFIG_IPDDP_DECAP=y
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
-+CONFIG_WAN_ROUTER=m
++# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
-+CONFIG_NET_SCHED=y
-+CONFIG_NET_SCH_CLK_JIFFIES=y
-+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
-+# CONFIG_NET_SCH_CLK_CPU is not set
-+
-+#
-+# Queueing/Scheduling
-+#
-+CONFIG_NET_SCH_CBQ=m
-+CONFIG_NET_SCH_HTB=m
-+CONFIG_NET_SCH_HFSC=m
-+CONFIG_NET_SCH_ATM=m
-+CONFIG_NET_SCH_PRIO=m
-+CONFIG_NET_SCH_RED=m
-+CONFIG_NET_SCH_SFQ=m
-+CONFIG_NET_SCH_TEQL=m
-+CONFIG_NET_SCH_TBF=m
-+CONFIG_NET_SCH_GRED=m
-+CONFIG_NET_SCH_DSMARK=m
-+CONFIG_NET_SCH_NETEM=m
-+CONFIG_NET_SCH_INGRESS=m
-+
-+#
-+# Classification
-+#
-+CONFIG_NET_CLS=y
-+# CONFIG_NET_CLS_BASIC is not set
-+CONFIG_NET_CLS_TCINDEX=m
-+CONFIG_NET_CLS_ROUTE4=m
-+CONFIG_NET_CLS_ROUTE=y
-+CONFIG_NET_CLS_FW=m
-+CONFIG_NET_CLS_U32=m
-+CONFIG_CLS_U32_PERF=y
-+# CONFIG_CLS_U32_MARK is not set
-+CONFIG_NET_CLS_RSVP=m
-+CONFIG_NET_CLS_RSVP6=m
-+# CONFIG_NET_EMATCH is not set
-+# CONFIG_NET_CLS_ACT is not set
-+CONFIG_NET_CLS_POLICE=y
-+CONFIG_NET_CLS_IND=y
-+CONFIG_NET_ESTIMATOR=y
++# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
-+CONFIG_IRDA=m
-+
-+#
-+# IrDA protocols
-+#
-+CONFIG_IRLAN=m
-+CONFIG_IRNET=m
-+CONFIG_IRCOMM=m
-+# CONFIG_IRDA_ULTRA is not set
-+
-+#
-+# IrDA options
-+#
-+CONFIG_IRDA_CACHE_LAST_LSAP=y
-+CONFIG_IRDA_FAST_RR=y
-+# CONFIG_IRDA_DEBUG is not set
-+
-+#
-+# Infrared-port device drivers
-+#
-+
-+#
-+# SIR device drivers
-+#
-+CONFIG_IRTTY_SIR=m
-+
-+#
-+# Dongle support
-+#
-+CONFIG_DONGLE=y
-+CONFIG_ESI_DONGLE=m
-+CONFIG_ACTISYS_DONGLE=m
-+CONFIG_TEKRAM_DONGLE=m
-+# CONFIG_TOIM3232_DONGLE is not set
-+CONFIG_LITELINK_DONGLE=m
-+CONFIG_MA600_DONGLE=m
-+CONFIG_GIRBIL_DONGLE=m
-+CONFIG_MCP2120_DONGLE=m
-+CONFIG_OLD_BELKIN_DONGLE=m
-+CONFIG_ACT200L_DONGLE=m
-+
-+#
-+# Old SIR device drivers
-+#
-+
-+#
-+# Old Serial dongle support
-+#
-+
-+#
-+# FIR device drivers
-+#
-+# CONFIG_NSC_FIR is not set
-+# CONFIG_WINBOND_FIR is not set
-+# CONFIG_SMC_IRCC_FIR is not set
-+# CONFIG_ALI_FIR is not set
-+# CONFIG_VIA_FIR is not set
-+CONFIG_BT=m
-+CONFIG_BT_L2CAP=m
-+CONFIG_BT_SCO=m
-+CONFIG_BT_RFCOMM=m
-+CONFIG_BT_RFCOMM_TTY=y
-+CONFIG_BT_BNEP=m
-+CONFIG_BT_BNEP_MC_FILTER=y
-+CONFIG_BT_BNEP_PROTO_FILTER=y
-+CONFIG_BT_HIDP=m
-+
-+#
-+# Bluetooth device drivers
-+#
-+CONFIG_BT_HCIUART=m
-+CONFIG_BT_HCIUART_H4=y
-+CONFIG_BT_HCIUART_BCSP=y
-+CONFIG_BT_HCIVHCI=m
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
-+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
@@ -64138,7 +65419,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
-+CONFIG_FW_LOADER=y
++# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
+
@@ -64164,14 +65445,14 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# Block devices
+#
-+CONFIG_BLK_DEV_FD=m
++# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
-+CONFIG_BLK_DEV_CRYPTOLOOP=m
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
-+CONFIG_BLK_DEV_RAM_SIZE=16384
++CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
@@ -64193,25 +65474,24 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
-+CONFIG_CHR_DEV_ST=m
-+CONFIG_CHR_DEV_OSST=m
-+CONFIG_BLK_DEV_SR=m
-+CONFIG_BLK_DEV_SR_VENDOR=y
-+CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
-+CONFIG_SCSI_CONSTANTS=y
-+CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
-+CONFIG_SCSI_SPI_ATTRS=m
-+CONFIG_SCSI_FC_ATTRS=m
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
@@ -64219,27 +65499,13 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
-+CONFIG_SCSI_SATA=m
++# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
-+CONFIG_MD=y
-+CONFIG_BLK_DEV_MD=y
-+CONFIG_MD_LINEAR=m
-+CONFIG_MD_RAID0=m
-+CONFIG_MD_RAID1=m
-+CONFIG_MD_RAID10=m
-+# CONFIG_MD_RAID456 is not set
-+CONFIG_MD_MULTIPATH=m
-+# CONFIG_MD_FAULTY is not set
-+CONFIG_BLK_DEV_DM=m
-+CONFIG_DM_CRYPT=m
-+CONFIG_DM_SNAPSHOT=m
-+CONFIG_DM_MIRROR=m
-+CONFIG_DM_ZERO=m
-+# CONFIG_DM_MULTIPATH is not set
++# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
@@ -64258,21 +65524,19 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# Network device support
+#
+CONFIG_NETDEVICES=y
-+CONFIG_DUMMY=m
-+CONFIG_BONDING=m
-+CONFIG_EQUALIZER=m
-+CONFIG_TUN=m
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
-+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
-+CONFIG_NET_ETHERNET=y
-+CONFIG_MII=m
++# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
@@ -64289,42 +65553,18 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# Wireless LAN (non-hamradio)
+#
-+CONFIG_NET_RADIO=y
-+# CONFIG_NET_WIRELESS_RTNETLINK is not set
-+
-+#
-+# Obsolete Wireless cards support (pre-802.11)
-+#
-+# CONFIG_STRIP is not set
-+# CONFIG_HOSTAP is not set
++# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
-+
-+#
-+# ATM drivers
-+#
-+# CONFIG_ATM_DUMMY is not set
-+CONFIG_ATM_TCP=m
-+CONFIG_PPP=m
-+CONFIG_PPP_MULTILINK=y
-+CONFIG_PPP_FILTER=y
-+CONFIG_PPP_ASYNC=m
-+CONFIG_PPP_SYNC_TTY=m
-+CONFIG_PPP_DEFLATE=m
-+# CONFIG_PPP_BSDCOMP is not set
-+# CONFIG_PPP_MPPE is not set
-+CONFIG_PPPOE=m
-+CONFIG_PPPOATM=m
++# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
-+CONFIG_NETCONSOLE=m
-+CONFIG_NETPOLL=y
-+# CONFIG_NETPOLL_RX is not set
-+CONFIG_NETPOLL_TRAP=y
-+CONFIG_NET_POLL_CONTROLLER=y
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
@@ -64357,7 +65597,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
-+CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
@@ -64374,7 +65614,6 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
-+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
@@ -64408,6 +65647,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
++CONFIG_HW_RANDOM_VIA=y
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
@@ -64419,6 +65659,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# CONFIG_MWAVE is not set
+# CONFIG_PC8736x_GPIO is not set
++# CONFIG_NSC_GPIO is not set
++# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
@@ -64544,19 +65786,10 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+
+#
-+# Firmware Drivers
-+#
-+# CONFIG_EDD is not set
-+# CONFIG_DELL_RBU is not set
-+# CONFIG_DCDBAS is not set
-+
-+#
+# File systems
+#
+CONFIG_EXT2_FS=y
-+CONFIG_EXT2_FS_XATTR=y
-+CONFIG_EXT2_FS_POSIX_ACL=y
-+CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
@@ -64567,33 +65800,20 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
-+CONFIG_REISERFS_PROC_INFO=y
-+CONFIG_REISERFS_FS_XATTR=y
-+CONFIG_REISERFS_FS_POSIX_ACL=y
-+CONFIG_REISERFS_FS_SECURITY=y
-+CONFIG_JFS_FS=m
-+CONFIG_JFS_POSIX_ACL=y
-+# CONFIG_JFS_SECURITY is not set
-+# CONFIG_JFS_DEBUG is not set
-+# CONFIG_JFS_STATISTICS is not set
-+CONFIG_FS_POSIX_ACL=y
-+CONFIG_XFS_FS=m
-+# CONFIG_XFS_QUOTA is not set
-+CONFIG_XFS_SECURITY=y
-+CONFIG_XFS_POSIX_ACL=y
-+# CONFIG_XFS_RT is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
-+CONFIG_MINIX_FS=m
-+CONFIG_ROMFS_FS=m
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
-+CONFIG_QUOTA=y
-+# CONFIG_QFMT_V1 is not set
-+CONFIG_QFMT_V2=y
-+CONFIG_QUOTACTL=y
++# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
-+CONFIG_AUTOFS_FS=m
-+CONFIG_AUTOFS4_FS=m
++CONFIG_AUTOFS_FS=y
++CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
@@ -64603,8 +65823,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
-+CONFIG_UDF_FS=m
-+CONFIG_UDF_NLS=y
++# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
@@ -64613,7 +65832,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
-+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
@@ -64631,61 +65850,38 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
-+CONFIG_AFFS_FS=m
-+CONFIG_HFS_FS=m
-+CONFIG_HFSPLUS_FS=m
-+CONFIG_BEFS_FS=m
-+# CONFIG_BEFS_DEBUG is not set
-+CONFIG_BFS_FS=m
-+CONFIG_EFS_FS=m
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
-+CONFIG_VXFS_FS=m
++# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
-+CONFIG_QNX4FS_FS=m
-+CONFIG_SYSV_FS=m
-+CONFIG_UFS_FS=m
-+# CONFIG_UFS_FS_WRITE is not set
-+# CONFIG_UFS_DEBUG is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
-+CONFIG_NFS_FS=m
++CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
-+CONFIG_NFS_V4=y
-+CONFIG_NFS_DIRECTIO=y
-+CONFIG_NFSD=m
-+CONFIG_NFSD_V3=y
-+# CONFIG_NFSD_V3_ACL is not set
-+CONFIG_NFSD_V4=y
-+CONFIG_NFSD_TCP=y
-+CONFIG_LOCKD=m
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
-+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
-+CONFIG_SUNRPC=m
-+CONFIG_SUNRPC_GSS=m
-+CONFIG_RPCSEC_GSS_KRB5=m
-+CONFIG_RPCSEC_GSS_SPKM3=m
-+CONFIG_SMB_FS=m
-+# CONFIG_SMB_NLS_DEFAULT is not set
-+CONFIG_CIFS=m
-+# CONFIG_CIFS_STATS is not set
-+# CONFIG_CIFS_WEAK_PW_HASH is not set
-+CONFIG_CIFS_XATTR=y
-+CONFIG_CIFS_POSIX=y
-+# CONFIG_CIFS_DEBUG2 is not set
-+# CONFIG_CIFS_EXPERIMENTAL is not set
-+CONFIG_NCP_FS=m
-+CONFIG_NCPFS_PACKET_SIGNING=y
-+CONFIG_NCPFS_IOCTL_LOCKING=y
-+CONFIG_NCPFS_STRONG=y
-+CONFIG_NCPFS_NFS_NS=y
-+CONFIG_NCPFS_OS2_NS=y
-+CONFIG_NCPFS_SMALLDOS=y
-+CONFIG_NCPFS_NLS=y
-+CONFIG_NCPFS_EXTRAS=y
++CONFIG_SUNRPC=y
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
@@ -64693,67 +65889,52 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+#
+# Partition Types
+#
-+CONFIG_PARTITION_ADVANCED=y
-+# CONFIG_ACORN_PARTITION is not set
-+CONFIG_OSF_PARTITION=y
-+# CONFIG_AMIGA_PARTITION is not set
-+# CONFIG_ATARI_PARTITION is not set
-+CONFIG_MAC_PARTITION=y
++# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
-+CONFIG_BSD_DISKLABEL=y
-+CONFIG_MINIX_SUBPARTITION=y
-+CONFIG_SOLARIS_X86_PARTITION=y
-+CONFIG_UNIXWARE_DISKLABEL=y
-+# CONFIG_LDM_PARTITION is not set
-+CONFIG_SGI_PARTITION=y
-+# CONFIG_ULTRIX_PARTITION is not set
-+CONFIG_SUN_PARTITION=y
-+# CONFIG_KARMA_PARTITION is not set
-+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
-+CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_CODEPAGE_737=m
-+CONFIG_NLS_CODEPAGE_775=m
-+CONFIG_NLS_CODEPAGE_850=m
-+CONFIG_NLS_CODEPAGE_852=m
-+CONFIG_NLS_CODEPAGE_855=m
-+CONFIG_NLS_CODEPAGE_857=m
-+CONFIG_NLS_CODEPAGE_860=m
-+CONFIG_NLS_CODEPAGE_861=m
-+CONFIG_NLS_CODEPAGE_862=m
-+CONFIG_NLS_CODEPAGE_863=m
-+CONFIG_NLS_CODEPAGE_864=m
-+CONFIG_NLS_CODEPAGE_865=m
-+CONFIG_NLS_CODEPAGE_866=m
-+CONFIG_NLS_CODEPAGE_869=m
-+CONFIG_NLS_CODEPAGE_936=m
-+CONFIG_NLS_CODEPAGE_950=m
-+CONFIG_NLS_CODEPAGE_932=m
-+CONFIG_NLS_CODEPAGE_949=m
-+CONFIG_NLS_CODEPAGE_874=m
-+CONFIG_NLS_ISO8859_8=m
-+CONFIG_NLS_CODEPAGE_1250=m
-+CONFIG_NLS_CODEPAGE_1251=m
-+CONFIG_NLS_ASCII=y
-+CONFIG_NLS_ISO8859_1=m
-+CONFIG_NLS_ISO8859_2=m
-+CONFIG_NLS_ISO8859_3=m
-+CONFIG_NLS_ISO8859_4=m
-+CONFIG_NLS_ISO8859_5=m
-+CONFIG_NLS_ISO8859_6=m
-+CONFIG_NLS_ISO8859_7=m
-+CONFIG_NLS_ISO8859_9=m
-+CONFIG_NLS_ISO8859_13=m
-+CONFIG_NLS_ISO8859_14=m
-+CONFIG_NLS_ISO8859_15=m
-+CONFIG_NLS_KOI8_R=m
-+CONFIG_NLS_KOI8_U=m
-+CONFIG_NLS_UTF8=m
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
@@ -64769,7 +65950,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_KERNEL=y
-+CONFIG_LOG_BUF_SHIFT=15
++CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
@@ -64783,6 +65964,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
@@ -64790,9 +65973,12 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
-+# CONFIG_DEBUG_RODATA is not set
++CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUG_RODATA is not set
++# CONFIG_4KSTACKS is not set
+
+#
+# Security options
@@ -64804,37 +65990,38 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
-+CONFIG_CRYPTO_HMAC=y
-+CONFIG_CRYPTO_NULL=m
-+CONFIG_CRYPTO_MD4=m
-+CONFIG_CRYPTO_MD5=y
-+CONFIG_CRYPTO_SHA1=y
-+CONFIG_CRYPTO_SHA256=m
-+CONFIG_CRYPTO_SHA512=m
-+CONFIG_CRYPTO_WP512=m
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=m
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
-+CONFIG_CRYPTO_DES=m
-+CONFIG_CRYPTO_BLOWFISH=m
-+CONFIG_CRYPTO_TWOFISH=m
-+CONFIG_CRYPTO_SERPENT=m
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
-+# CONFIG_CRYPTO_AES_X86_64 is not set
-+CONFIG_CRYPTO_CAST5=m
-+CONFIG_CRYPTO_CAST6=m
-+CONFIG_CRYPTO_TEA=m
-+CONFIG_CRYPTO_ARC4=m
-+CONFIG_CRYPTO_KHAZAD=m
++# CONFIG_CRYPTO_AES_586 is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
-+CONFIG_CRYPTO_DEFLATE=m
-+CONFIG_CRYPTO_MICHAEL_MIC=m
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
++# CONFIG_CRYPTO_DEV_PADLOCK is not set
+CONFIG_XEN=y
-+CONFIG_XEN_INTERFACE_VERSION=0x00030206
++CONFIG_XEN_INTERFACE_VERSION=0x00030207
+
+#
+# XEN
@@ -64844,8 +66031,12 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+# CONFIG_XEN_BACKEND is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
++CONFIG_XEN_SCSI_FRONTEND=m
++# CONFIG_XEN_GRANT_DEV is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
@@ -64859,29 +66050,51 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-
+CONFIG_XEN_SMPBOOT=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
-+# CONFIG_XEN_GRANT_DEV is not set
+
+#
+# Library routines
+#
-+CONFIG_CRC_CCITT=m
++# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
-+CONFIG_CRC32=y
++# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
-+CONFIG_ZLIB_DEFLATE=m
-+CONFIG_TEXTSEARCH=y
-+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_PLIST=y
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen_ia64
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen_ia64 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,1697 @@
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_PENDING_IRQ=y
++CONFIG_X86_SMP=y
++CONFIG_X86_BIOS_REBOOT=y
++CONFIG_X86_TRAMPOLINE=y
++CONFIG_X86_NO_TSS=y
++CONFIG_X86_NO_IDT=y
++CONFIG_KTIME_SCALAR=y
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xenU_x86_64
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xenU_x86_64 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xenU_x86_64 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,906 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
-+# Mon Dec 17 13:38:29 2007
++# Mon Feb 18 10:42:42 2008
+#
++CONFIG_X86_64=y
++CONFIG_64BIT=y
++CONFIG_X86=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_MMU=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_X86_CMPXCHG=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_GENERIC_IOMAP=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_DMI=y
++CONFIG_AUDIT_ARCH=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
@@ -64895,25 +66108,24 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# General setup
+#
+CONFIG_LOCALVERSION=""
-+CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
-+CONFIG_POSIX_MQUEUE=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
++# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
-+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
+CONFIG_SYSCTL=y
+CONFIG_KALLSYMS=y
-+CONFIG_KALLSYMS_ALL=y
-+CONFIG_KALLSYMS_EXTRA_PASS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
@@ -64935,15 +66147,17 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
-+CONFIG_MODVERSIONS=y
-+CONFIG_MODULE_SRCVERSION_ALL=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
++# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
++CONFIG_LSF=y
+
+#
+# IO Schedulers
@@ -64961,151 +66175,77 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# Processor type and features
+#
-+CONFIG_IA64=y
-+CONFIG_64BIT=y
-+CONFIG_MMU=y
-+CONFIG_SWIOTLB=y
-+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-+CONFIG_GENERIC_FIND_NEXT_BIT=y
-+CONFIG_GENERIC_CALIBRATE_DELAY=y
-+CONFIG_TIME_INTERPOLATION=y
-+CONFIG_DMI=y
-+CONFIG_EFI=y
-+CONFIG_GENERIC_IOMAP=y
-+CONFIG_XEN=y
-+CONFIG_XEN_IA64_EXPOSE_P2M=y
-+CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y
-+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-+CONFIG_DMA_IS_DMA32=y
-+CONFIG_AUDIT_ARCH=y
-+CONFIG_IA64_GENERIC=y
-+# CONFIG_IA64_DIG is not set
-+# CONFIG_IA64_HP_ZX1 is not set
-+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
-+# CONFIG_IA64_SGI_SN2 is not set
-+# CONFIG_IA64_HP_SIM is not set
-+# CONFIG_IA64_XEN is not set
-+# CONFIG_ITANIUM is not set
-+CONFIG_MCKINLEY=y
-+# CONFIG_IA64_PAGE_SIZE_4KB is not set
-+# CONFIG_IA64_PAGE_SIZE_8KB is not set
-+CONFIG_IA64_PAGE_SIZE_16KB=y
-+# CONFIG_IA64_PAGE_SIZE_64KB is not set
-+CONFIG_PGTABLE_3=y
-+# CONFIG_PGTABLE_4 is not set
-+CONFIG_HZ_100=y
-+# CONFIG_HZ_250 is not set
-+# CONFIG_HZ_1000 is not set
-+CONFIG_HZ=100
-+CONFIG_IA64_L1_CACHE_SHIFT=7
-+CONFIG_IA64_CYCLONE=y
-+CONFIG_IOSAPIC=y
-+# CONFIG_IA64_SGI_SN_XP is not set
-+CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_X86_PC=y
++# CONFIG_X86_VSMP is not set
++# CONFIG_MK8 is not set
++# CONFIG_MPSC is not set
++CONFIG_GENERIC_CPU=y
++CONFIG_X86_64_XEN=y
++CONFIG_X86_NO_TSS=y
++CONFIG_X86_NO_IDT=y
++CONFIG_X86_L1_CACHE_BYTES=128
++CONFIG_X86_L1_CACHE_SHIFT=7
++CONFIG_X86_INTERNODE_CACHE_BYTES=128
++CONFIG_X86_GOOD_APIC=y
++# CONFIG_MICROCODE is not set
++# CONFIG_X86_MSR is not set
++CONFIG_X86_CPUID=y
++CONFIG_X86_XEN_GENAPIC=y
+CONFIG_SMP=y
-+CONFIG_NR_CPUS=16
-+CONFIG_HOTPLUG_CPU=y
-+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-+# CONFIG_SCHED_SMT is not set
-+# CONFIG_PERMIT_BSP_REMOVE is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
++CONFIG_PREEMPT_BKL=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
-+# CONFIG_FLATMEM_MANUAL is not set
-+CONFIG_DISCONTIGMEM_MANUAL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
-+CONFIG_DISCONTIGMEM=y
++CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
-+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
-+# CONFIG_MIGRATION is not set
+CONFIG_RESOURCES_64BIT=y
-+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
-+CONFIG_ARCH_FLATMEM_ENABLE=y
-+CONFIG_ARCH_SPARSEMEM_ENABLE=y
-+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
-+CONFIG_NUMA=y
-+CONFIG_NODES_SHIFT=10
-+CONFIG_VIRTUAL_MEM_MAP=y
-+CONFIG_HOLES_IN_ZONE=y
-+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
-+CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y
-+# CONFIG_IA32_SUPPORT is not set
-+# CONFIG_IA64_MCA_RECOVERY is not set
-+CONFIG_PERFMON=y
-+CONFIG_IA64_PALINFO=y
-+CONFIG_SGI_SN=y
-+
-+#
-+# SN Devices
-+#
-+# CONFIG_SGI_IOC3 is not set
-+CONFIG_KEXEC=y
-+
-+#
-+# Firmware Drivers
-+#
-+CONFIG_EFI_VARS=y
-+CONFIG_EFI_PCDP=y
-+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=y
-+
-+#
-+# Power management and ACPI
-+#
-+CONFIG_PM=y
-+CONFIG_PM_LEGACY=y
-+# CONFIG_PM_DEBUG is not set
-+
-+#
-+# ACPI (Advanced Configuration and Power Interface) Support
-+#
-+CONFIG_ACPI=y
-+CONFIG_ACPI_BUTTON=y
-+CONFIG_ACPI_FAN=y
-+# CONFIG_ACPI_DOCK is not set
-+CONFIG_ACPI_PROCESSOR=y
-+CONFIG_ACPI_HOTPLUG_CPU=y
-+CONFIG_ACPI_THERMAL=y
-+CONFIG_ACPI_NUMA=y
-+CONFIG_ACPI_BLACKLIST_YEAR=0
-+# CONFIG_ACPI_DEBUG is not set
-+CONFIG_ACPI_EC=y
-+CONFIG_ACPI_POWER=y
-+CONFIG_ACPI_SYSTEM=y
-+CONFIG_ACPI_CONTAINER=y
++CONFIG_NR_CPUS=8
++CONFIG_HOTPLUG_CPU=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_SWIOTLB=y
++# CONFIG_CRASH_DUMP is not set
++CONFIG_PHYSICAL_START=0x200000
++CONFIG_SECCOMP=y
++CONFIG_HZ_100=y
++# CONFIG_HZ_250 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=100
++# CONFIG_REORDER is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_ISA_DMA_API=y
++CONFIG_GENERIC_PENDING_IRQ=y
+
+#
-+# CPU Frequency scaling
++# Bus options (PCI etc.)
+#
-+# CONFIG_CPU_FREQ is not set
++# CONFIG_PCI is not set
+
+#
-+# Bus options (PCI, PCMCIA)
++# PCCARD (PCMCIA/CardBus) support
+#
-+CONFIG_PCI=y
-+CONFIG_PCI_DOMAINS=y
-+CONFIG_XEN_PCIDEV_FRONTEND=y
-+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
-+# CONFIG_PCIEPORTBUS is not set
-+# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
-+CONFIG_HOTPLUG_PCI=y
-+# CONFIG_HOTPLUG_PCI_FAKE is not set
-+CONFIG_HOTPLUG_PCI_ACPI=y
-+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
-+# CONFIG_HOTPLUG_PCI_CPCI is not set
-+# CONFIG_HOTPLUG_PCI_SHPC is not set
-+# CONFIG_HOTPLUG_PCI_SGI is not set
+
+#
-+# PCCARD (PCMCIA/CardBus) support
++# Executable file formats / Emulations
+#
-+# CONFIG_PCCARD is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_IA32_EMULATION=y
++CONFIG_IA32_AOUT=y
++CONFIG_COMPAT=y
++CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Networking
@@ -65123,18 +66263,17 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
-+CONFIG_IP_MULTICAST=y
++# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
-+# CONFIG_IP_MROUTE is not set
-+CONFIG_ARPD=y
-+CONFIG_SYN_COOKIES=y
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
@@ -65142,40 +66281,14 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
-+CONFIG_INET_DIAG=y
-+CONFIG_INET_TCP_DIAG=y
++# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
-+
-+#
-+# IP: Virtual Server Configuration
-+#
-+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
-+CONFIG_NETFILTER=y
-+# CONFIG_NETFILTER_DEBUG is not set
-+CONFIG_BRIDGE_NETFILTER=y
-+
-+#
-+# Core Netfilter Configuration
-+#
-+# CONFIG_NETFILTER_NETLINK is not set
-+# CONFIG_NF_CONNTRACK is not set
-+# CONFIG_NETFILTER_XTABLES is not set
-+
-+#
-+# IP: Netfilter Configuration
-+#
-+# CONFIG_IP_NF_CONNTRACK is not set
-+# CONFIG_IP_NF_QUEUE is not set
-+
-+#
-+# Bridge: Netfilter Configuration
-+#
-+# CONFIG_BRIDGE_NF_EBTABLES is not set
++# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
@@ -65192,10 +66305,9 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
-+CONFIG_BRIDGE=y
++# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
-+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
@@ -65227,7 +66339,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
-+CONFIG_FW_LOADER=y
++# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
+
@@ -65249,22 +66361,15 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# Plug and Play support
+#
-+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
-+# CONFIG_BLK_CPQ_DA is not set
-+CONFIG_BLK_CPQ_CISS_DA=y
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_BLK_DEV_CRYPTOLOOP=y
++CONFIG_BLK_DEV_LOOP=m
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
-+# CONFIG_BLK_DEV_SX8 is not set
-+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
@@ -65276,265 +66381,94 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# ATA/ATAPI/MFM/RLL support
+#
-+CONFIG_IDE=y
-+CONFIG_IDE_MAX_HWIFS=4
-+CONFIG_BLK_DEV_IDE=y
-+
-+#
-+# Please see Documentation/ide.txt for help/info on IDE drives
-+#
-+# CONFIG_BLK_DEV_IDE_SATA is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+CONFIG_BLK_DEV_IDECD=y
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+CONFIG_BLK_DEV_IDEFLOPPY=y
-+CONFIG_BLK_DEV_IDESCSI=y
-+# CONFIG_IDE_TASK_IOCTL is not set
-+
-+#
-+# IDE chipset support/bugfixes
-+#
-+# CONFIG_IDE_GENERIC is not set
-+CONFIG_BLK_DEV_IDEPCI=y
-+# CONFIG_IDEPCI_SHARE_IRQ is not set
-+# CONFIG_BLK_DEV_OFFBOARD is not set
-+CONFIG_BLK_DEV_GENERIC=y
-+# CONFIG_BLK_DEV_OPTI621 is not set
-+CONFIG_BLK_DEV_IDEDMA_PCI=y
-+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-+CONFIG_IDEDMA_PCI_AUTO=y
-+# CONFIG_IDEDMA_ONLYDISK is not set
-+# CONFIG_BLK_DEV_AEC62XX is not set
-+# CONFIG_BLK_DEV_ALI15X3 is not set
-+# CONFIG_BLK_DEV_AMD74XX is not set
-+CONFIG_BLK_DEV_CMD64X=y
-+# CONFIG_BLK_DEV_TRIFLEX is not set
-+# CONFIG_BLK_DEV_CY82C693 is not set
-+# CONFIG_BLK_DEV_CS5520 is not set
-+# CONFIG_BLK_DEV_CS5530 is not set
-+# CONFIG_BLK_DEV_HPT34X is not set
-+# CONFIG_BLK_DEV_HPT366 is not set
-+# CONFIG_BLK_DEV_SC1200 is not set
-+CONFIG_BLK_DEV_PIIX=y
-+# CONFIG_BLK_DEV_IT821X is not set
-+# CONFIG_BLK_DEV_NS87415 is not set
-+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-+# CONFIG_BLK_DEV_SVWKS is not set
-+# CONFIG_BLK_DEV_SIIMAGE is not set
-+# CONFIG_BLK_DEV_SLC90E66 is not set
-+# CONFIG_BLK_DEV_TRM290 is not set
-+# CONFIG_BLK_DEV_VIA82CXXX is not set
-+# CONFIG_IDE_ARM is not set
-+CONFIG_BLK_DEV_IDEDMA=y
-+# CONFIG_IDEDMA_IVB is not set
-+CONFIG_IDEDMA_AUTO=y
-+# CONFIG_BLK_DEV_HD is not set
++# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
-+CONFIG_SCSI=y
++CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_CHR_DEV_ST=y
-+CONFIG_CHR_DEV_OSST=y
-+CONFIG_BLK_DEV_SR=y
-+CONFIG_BLK_DEV_SR_VENDOR=y
-+CONFIG_CHR_DEV_SG=y
++CONFIG_BLK_DEV_SD=m
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
-+CONFIG_SCSI_MULTI_LUN=y
-+CONFIG_SCSI_CONSTANTS=y
-+CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
-+CONFIG_SCSI_SPI_ATTRS=y
-+CONFIG_SCSI_FC_ATTRS=y
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
-+CONFIG_SCSI_SAS_ATTRS=y
++# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
-+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-+# CONFIG_SCSI_3W_9XXX is not set
-+# CONFIG_SCSI_ACARD is not set
-+# CONFIG_SCSI_AACRAID is not set
-+# CONFIG_SCSI_AIC7XXX is not set
-+# CONFIG_SCSI_AIC7XXX_OLD is not set
-+# CONFIG_SCSI_AIC79XX is not set
-+# CONFIG_MEGARAID_NEWGEN is not set
-+# CONFIG_MEGARAID_LEGACY is not set
-+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
-+# CONFIG_SCSI_HPTIOP is not set
-+# CONFIG_SCSI_DMX3191D is not set
-+# CONFIG_SCSI_FUTURE_DOMAIN is not set
-+# CONFIG_SCSI_IPS is not set
-+# CONFIG_SCSI_INITIO is not set
-+# CONFIG_SCSI_INIA100 is not set
-+CONFIG_SCSI_SYM53C8XX_2=y
-+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-+CONFIG_SCSI_SYM53C8XX_MMIO=y
-+# CONFIG_SCSI_IPR is not set
-+CONFIG_SCSI_QLOGIC_1280=y
-+# CONFIG_SCSI_QLA_FC is not set
-+# CONFIG_SCSI_LPFC is not set
-+# CONFIG_SCSI_DC395x is not set
-+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
-+CONFIG_MD=y
-+# CONFIG_BLK_DEV_MD is not set
-+CONFIG_BLK_DEV_DM=y
-+CONFIG_DM_CRYPT=m
-+CONFIG_DM_SNAPSHOT=y
-+CONFIG_DM_MIRROR=m
-+CONFIG_DM_ZERO=m
-+CONFIG_DM_MULTIPATH=m
-+CONFIG_DM_MULTIPATH_EMC=m
++# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
-+CONFIG_FUSION=y
-+CONFIG_FUSION_SPI=y
-+# CONFIG_FUSION_FC is not set
-+CONFIG_FUSION_SAS=y
-+CONFIG_FUSION_MAX_SGE=128
-+# CONFIG_FUSION_CTL is not set
++# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
-+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
-+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
-+CONFIG_DUMMY=y
++# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
-+CONFIG_TUN=y
-+
-+#
-+# ARCnet devices
-+#
-+CONFIG_ARCNET=y
-+# CONFIG_ARCNET_1201 is not set
-+# CONFIG_ARCNET_1051 is not set
-+# CONFIG_ARCNET_RAW is not set
-+# CONFIG_ARCNET_CAP is not set
-+# CONFIG_ARCNET_COM90xx is not set
-+# CONFIG_ARCNET_COM90xxIO is not set
-+# CONFIG_ARCNET_RIM_I is not set
-+# CONFIG_ARCNET_COM20020 is not set
++# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
-+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
-+CONFIG_NET_ETHERNET=y
-+CONFIG_MII=y
-+# CONFIG_HAPPYMEAL is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_CASSINI is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+
-+#
-+# Tulip family network device support
-+#
-+CONFIG_NET_TULIP=y
-+# CONFIG_DE2104X is not set
-+CONFIG_TULIP=y
-+CONFIG_TULIP_MWI=y
-+CONFIG_TULIP_MMIO=y
-+CONFIG_TULIP_NAPI=y
-+CONFIG_TULIP_NAPI_HW_MITIGATION=y
-+# CONFIG_DE4X5 is not set
-+# CONFIG_WINBOND_840 is not set
-+# CONFIG_DM9102 is not set
-+# CONFIG_ULI526X is not set
-+# CONFIG_HP100 is not set
-+CONFIG_NET_PCI=y
-+# CONFIG_PCNET32 is not set
-+# CONFIG_AMD8111_ETH is not set
-+# CONFIG_ADAPTEC_STARFIRE is not set
-+# CONFIG_B44 is not set
-+# CONFIG_FORCEDETH is not set
-+# CONFIG_DGRS is not set
-+CONFIG_EEPRO100=y
-+CONFIG_E100=y
-+# CONFIG_FEALNX is not set
-+# CONFIG_NATSEMI is not set
-+# CONFIG_NE2K_PCI is not set
-+# CONFIG_8139CP is not set
-+# CONFIG_8139TOO is not set
-+# CONFIG_SIS900 is not set
-+# CONFIG_EPIC100 is not set
-+# CONFIG_SUNDANCE is not set
-+# CONFIG_VIA_RHINE is not set
++# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+CONFIG_E1000=y
-+# CONFIG_E1000_NAPI is not set
-+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_R8169 is not set
-+# CONFIG_SIS190 is not set
-+# CONFIG_SKGE is not set
-+# CONFIG_SKY2 is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_VIA_VELOCITY is not set
-+CONFIG_TIGON3=y
-+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
-+# CONFIG_CHELSIO_T1 is not set
-+# CONFIG_IXGB is not set
-+# CONFIG_S2IO is not set
-+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
-+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
@@ -65545,32 +66479,17 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# Wan interfaces
+#
+# CONFIG_WAN is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
-+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
-+CONFIG_NETCONSOLE=y
-+CONFIG_NETPOLL=y
-+# CONFIG_NETPOLL_RX is not set
-+# CONFIG_NETPOLL_TRAP is not set
-+CONFIG_NET_POLL_CONTROLLER=y
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
-+CONFIG_ISDN=m
-+
-+#
-+# Old ISDN4Linux
-+#
-+# CONFIG_ISDN_I4L is not set
-+
-+#
-+# CAPI subsystem
-+#
-+# CONFIG_ISDN_CAPI is not set
++# CONFIG_ISDN is not set
+
+#
+# Telephony Support
@@ -65586,12 +66505,12 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
-+CONFIG_INPUT_MOUSEDEV_PSAUX=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-+CONFIG_INPUT_JOYDEV=y
++# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
-+CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
@@ -65603,10 +66522,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
-+CONFIG_INPUT_MOUSE=y
-+CONFIG_MOUSE_PS2=y
-+# CONFIG_MOUSE_SERIAL is not set
-+# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
@@ -65616,15 +66532,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
-+# CONFIG_SERIO_SERPORT is not set
-+# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
-+CONFIG_GAMEPORT=y
-+# CONFIG_GAMEPORT_NS558 is not set
-+# CONFIG_GAMEPORT_L4 is not set
-+# CONFIG_GAMEPORT_EMU10K1 is not set
-+# CONFIG_GAMEPORT_FM801 is not set
++# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
@@ -65633,23 +66545,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
-+CONFIG_SERIAL_NONSTANDARD=y
-+# CONFIG_COMPUTONE is not set
-+# CONFIG_ROCKETPORT is not set
-+# CONFIG_CYCLADES is not set
-+# CONFIG_DIGIEPCA is not set
-+# CONFIG_MOXA_INTELLIO is not set
-+# CONFIG_MOXA_SMARTIO is not set
-+# CONFIG_ISI is not set
-+# CONFIG_SYNCLINKMP is not set
-+# CONFIG_SYNCLINK_GT is not set
-+# CONFIG_N_HDLC is not set
-+# CONFIG_SPECIALIX is not set
-+# CONFIG_SX is not set
-+# CONFIG_RIO is not set
-+# CONFIG_STALDRV is not set
-+# CONFIG_SGI_SNSC is not set
-+# CONFIG_SGI_TIOCX is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
@@ -65658,8 +66554,6 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# Non-8250 serial port support
+#
-+# CONFIG_SERIAL_SGI_L1_CONSOLE is not set
-+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
@@ -65673,33 +66567,20 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
-+# CONFIG_HW_RANDOM is not set
-+CONFIG_EFI_RTC=y
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
-+CONFIG_AGP=y
-+# CONFIG_AGP_SIS is not set
-+# CONFIG_AGP_VIA is not set
-+CONFIG_AGP_I460=y
-+# CONFIG_AGP_HP_ZX1 is not set
-+# CONFIG_AGP_SGI_TIOCA is not set
-+CONFIG_DRM=y
-+# CONFIG_DRM_TDFX is not set
-+# CONFIG_DRM_R128 is not set
-+# CONFIG_DRM_RADEON is not set
-+# CONFIG_DRM_MGA is not set
-+# CONFIG_DRM_SIS is not set
-+# CONFIG_DRM_VIA is not set
-+# CONFIG_DRM_SAVAGE is not set
++# CONFIG_MWAVE is not set
++# CONFIG_PC8736x_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
-+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
-+# CONFIG_MMTIMER is not set
+
+#
+# TPM devices
@@ -65710,55 +66591,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# I2C support
+#
-+CONFIG_I2C=y
-+CONFIG_I2C_CHARDEV=y
-+
-+#
-+# I2C Algorithms
-+#
-+CONFIG_I2C_ALGOBIT=y
-+CONFIG_I2C_ALGOPCF=y
-+# CONFIG_I2C_ALGOPCA is not set
-+
-+#
-+# I2C Hardware Bus support
-+#
-+# CONFIG_I2C_ALI1535 is not set
-+# CONFIG_I2C_ALI1563 is not set
-+# CONFIG_I2C_ALI15X3 is not set
-+# CONFIG_I2C_AMD756 is not set
-+# CONFIG_I2C_AMD8111 is not set
-+# CONFIG_I2C_I801 is not set
-+# CONFIG_I2C_I810 is not set
-+# CONFIG_I2C_PIIX4 is not set
-+# CONFIG_I2C_NFORCE2 is not set
-+# CONFIG_I2C_OCORES is not set
-+# CONFIG_I2C_PARPORT_LIGHT is not set
-+# CONFIG_I2C_PROSAVAGE is not set
-+# CONFIG_I2C_SAVAGE4 is not set
-+# CONFIG_I2C_SIS5595 is not set
-+# CONFIG_I2C_SIS630 is not set
-+# CONFIG_I2C_SIS96X is not set
-+# CONFIG_I2C_STUB is not set
-+# CONFIG_I2C_VIA is not set
-+# CONFIG_I2C_VIAPRO is not set
-+# CONFIG_I2C_VOODOO3 is not set
-+# CONFIG_I2C_PCA_ISA is not set
-+
-+#
-+# Miscellaneous I2C Chip support
-+#
-+# CONFIG_SENSORS_DS1337 is not set
-+# CONFIG_SENSORS_DS1374 is not set
-+# CONFIG_SENSORS_EEPROM is not set
-+# CONFIG_SENSORS_PCF8574 is not set
-+# CONFIG_SENSORS_PCA9539 is not set
-+# CONFIG_SENSORS_PCF8591 is not set
-+# CONFIG_SENSORS_MAX6875 is not set
-+# CONFIG_I2C_DEBUG_CORE is not set
-+# CONFIG_I2C_DEBUG_ALGO is not set
-+# CONFIG_I2C_DEBUG_BUS is not set
-+# CONFIG_I2C_DEBUG_CHIP is not set
++# CONFIG_I2C is not set
+
+#
+# SPI support
@@ -65773,48 +66606,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# Hardware Monitoring support
+#
-+CONFIG_HWMON=y
++# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
-+# CONFIG_SENSORS_ABITUGURU is not set
-+# CONFIG_SENSORS_ADM1021 is not set
-+# CONFIG_SENSORS_ADM1025 is not set
-+# CONFIG_SENSORS_ADM1026 is not set
-+# CONFIG_SENSORS_ADM1031 is not set
-+# CONFIG_SENSORS_ADM9240 is not set
-+# CONFIG_SENSORS_ASB100 is not set
-+# CONFIG_SENSORS_ATXP1 is not set
-+# CONFIG_SENSORS_DS1621 is not set
-+# CONFIG_SENSORS_F71805F is not set
-+# CONFIG_SENSORS_FSCHER is not set
-+# CONFIG_SENSORS_FSCPOS is not set
-+# CONFIG_SENSORS_GL518SM is not set
-+# CONFIG_SENSORS_GL520SM is not set
-+# CONFIG_SENSORS_IT87 is not set
-+# CONFIG_SENSORS_LM63 is not set
-+# CONFIG_SENSORS_LM75 is not set
-+# CONFIG_SENSORS_LM77 is not set
-+# CONFIG_SENSORS_LM78 is not set
-+# CONFIG_SENSORS_LM80 is not set
-+# CONFIG_SENSORS_LM83 is not set
-+# CONFIG_SENSORS_LM85 is not set
-+# CONFIG_SENSORS_LM87 is not set
-+# CONFIG_SENSORS_LM90 is not set
-+# CONFIG_SENSORS_LM92 is not set
-+# CONFIG_SENSORS_MAX1619 is not set
-+# CONFIG_SENSORS_PC87360 is not set
-+# CONFIG_SENSORS_SIS5595 is not set
-+# CONFIG_SENSORS_SMSC47M1 is not set
-+# CONFIG_SENSORS_SMSC47M192 is not set
-+# CONFIG_SENSORS_SMSC47B397 is not set
-+# CONFIG_SENSORS_VIA686A is not set
-+# CONFIG_SENSORS_VT8231 is not set
-+# CONFIG_SENSORS_W83781D is not set
-+# CONFIG_SENSORS_W83791D is not set
-+# CONFIG_SENSORS_W83792D is not set
-+# CONFIG_SENSORS_W83L785TS is not set
-+# CONFIG_SENSORS_W83627HF is not set
-+# CONFIG_SENSORS_W83627EHF is not set
-+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
@@ -65823,115 +66616,18 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# Multimedia devices
+#
-+CONFIG_VIDEO_DEV=y
-+CONFIG_VIDEO_V4L1=y
-+CONFIG_VIDEO_V4L1_COMPAT=y
-+CONFIG_VIDEO_V4L2=y
-+
-+#
-+# Video Capture Adapters
-+#
-+
-+#
-+# Video Capture Adapters
-+#
-+# CONFIG_VIDEO_ADV_DEBUG is not set
-+# CONFIG_VIDEO_VIVI is not set
-+# CONFIG_VIDEO_BT848 is not set
-+# CONFIG_VIDEO_CPIA is not set
-+# CONFIG_VIDEO_CPIA2 is not set
-+# CONFIG_VIDEO_SAA5246A is not set
-+# CONFIG_VIDEO_SAA5249 is not set
-+# CONFIG_TUNER_3036 is not set
-+# CONFIG_VIDEO_STRADIS is not set
-+# CONFIG_VIDEO_ZORAN is not set
-+# CONFIG_VIDEO_SAA7134 is not set
-+# CONFIG_VIDEO_MXB is not set
-+# CONFIG_VIDEO_DPC is not set
-+# CONFIG_VIDEO_HEXIUM_ORION is not set
-+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
-+# CONFIG_VIDEO_CX88 is not set
-+
-+#
-+# Encoders and Decoders
-+#
-+# CONFIG_VIDEO_MSP3400 is not set
-+# CONFIG_VIDEO_CS53L32A is not set
-+# CONFIG_VIDEO_TLV320AIC23B is not set
-+# CONFIG_VIDEO_WM8775 is not set
-+# CONFIG_VIDEO_WM8739 is not set
-+# CONFIG_VIDEO_CX2341X is not set
-+# CONFIG_VIDEO_CX25840 is not set
-+# CONFIG_VIDEO_SAA711X is not set
-+# CONFIG_VIDEO_SAA7127 is not set
-+# CONFIG_VIDEO_UPD64031A is not set
-+# CONFIG_VIDEO_UPD64083 is not set
-+
-+#
-+# V4L USB devices
-+#
-+# CONFIG_VIDEO_PVRUSB2 is not set
-+# CONFIG_VIDEO_EM28XX is not set
-+# CONFIG_USB_VICAM is not set
-+# CONFIG_USB_IBMCAM is not set
-+# CONFIG_USB_KONICAWC is not set
-+# CONFIG_USB_QUICKCAM_MESSENGER is not set
-+# CONFIG_USB_ET61X251 is not set
-+# CONFIG_VIDEO_OVCAMCHIP is not set
-+# CONFIG_USB_W9968CF is not set
-+# CONFIG_USB_OV511 is not set
-+# CONFIG_USB_SE401 is not set
-+# CONFIG_USB_SN9C102 is not set
-+# CONFIG_USB_STV680 is not set
-+# CONFIG_USB_ZC0301 is not set
-+# CONFIG_USB_PWC is not set
-+
-+#
-+# Radio Adapters
-+#
-+# CONFIG_RADIO_GEMTEK_PCI is not set
-+# CONFIG_RADIO_MAXIRADIO is not set
-+# CONFIG_RADIO_MAESTRO is not set
-+# CONFIG_USB_DSBR is not set
++# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
-+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
-+CONFIG_FB=y
-+CONFIG_FB_CFB_FILLRECT=y
-+CONFIG_FB_CFB_COPYAREA=y
-+CONFIG_FB_CFB_IMAGEBLIT=y
-+# CONFIG_FB_MACMODES is not set
-+# CONFIG_FB_BACKLIGHT is not set
-+CONFIG_FB_MODE_HELPERS=y
-+# CONFIG_FB_TILEBLITTING is not set
-+# CONFIG_FB_CIRRUS is not set
-+# CONFIG_FB_PM2 is not set
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_ASILIANT is not set
-+# CONFIG_FB_IMSTT is not set
-+# CONFIG_FB_S1D13XXX is not set
-+# CONFIG_FB_NVIDIA is not set
-+# CONFIG_FB_RIVA is not set
-+# CONFIG_FB_MATROX is not set
-+# CONFIG_FB_RADEON is not set
-+# CONFIG_FB_ATY128 is not set
-+# CONFIG_FB_ATY is not set
-+# CONFIG_FB_SAVAGE is not set
-+# CONFIG_FB_SIS is not set
-+# CONFIG_FB_NEOMAGIC is not set
-+# CONFIG_FB_KYRO is not set
-+# CONFIG_FB_3DFX is not set
-+# CONFIG_FB_VOODOO1 is not set
-+# CONFIG_FB_TRIDENT is not set
-+# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB is not set
+
+#
+# Console display driver support
@@ -65939,268 +66635,25 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
-+CONFIG_FRAMEBUFFER_CONSOLE=y
-+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-+# CONFIG_FONTS is not set
-+CONFIG_FONT_8x8=y
-+CONFIG_FONT_8x16=y
-+
-+#
-+# Logo configuration
-+#
-+CONFIG_LOGO=y
-+# CONFIG_LOGO_LINUX_MONO is not set
-+# CONFIG_LOGO_LINUX_VGA16 is not set
-+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
-+CONFIG_SOUND=y
-+
-+#
-+# Advanced Linux Sound Architecture
-+#
-+CONFIG_SND=y
-+CONFIG_SND_TIMER=y
-+CONFIG_SND_PCM=y
-+CONFIG_SND_HWDEP=y
-+CONFIG_SND_RAWMIDI=y
-+CONFIG_SND_SEQUENCER=y
-+CONFIG_SND_SEQ_DUMMY=y
-+CONFIG_SND_OSSEMUL=y
-+CONFIG_SND_MIXER_OSS=y
-+CONFIG_SND_PCM_OSS=y
-+CONFIG_SND_PCM_OSS_PLUGINS=y
-+CONFIG_SND_SEQUENCER_OSS=y
-+# CONFIG_SND_DYNAMIC_MINORS is not set
-+CONFIG_SND_SUPPORT_OLD_API=y
-+CONFIG_SND_VERBOSE_PROCFS=y
-+# CONFIG_SND_VERBOSE_PRINTK is not set
-+# CONFIG_SND_DEBUG is not set
-+
-+#
-+# Generic devices
-+#
-+CONFIG_SND_MPU401_UART=y
-+CONFIG_SND_OPL3_LIB=y
-+CONFIG_SND_AC97_CODEC=y
-+CONFIG_SND_AC97_BUS=y
-+CONFIG_SND_DUMMY=y
-+CONFIG_SND_VIRMIDI=y
-+# CONFIG_SND_MTPAV is not set
-+CONFIG_SND_SERIAL_U16550=y
-+CONFIG_SND_MPU401=y
-+
-+#
-+# PCI devices
-+#
-+# CONFIG_SND_AD1889 is not set
-+# CONFIG_SND_ALS300 is not set
-+# CONFIG_SND_ALI5451 is not set
-+CONFIG_SND_ATIIXP=y
-+# CONFIG_SND_ATIIXP_MODEM is not set
-+# CONFIG_SND_AU8810 is not set
-+# CONFIG_SND_AU8820 is not set
-+# CONFIG_SND_AU8830 is not set
-+# CONFIG_SND_AZT3328 is not set
-+# CONFIG_SND_BT87X is not set
-+# CONFIG_SND_CA0106 is not set
-+# CONFIG_SND_CMIPCI is not set
-+# CONFIG_SND_CS4281 is not set
-+# CONFIG_SND_CS46XX is not set
-+# CONFIG_SND_DARLA20 is not set
-+# CONFIG_SND_GINA20 is not set
-+# CONFIG_SND_LAYLA20 is not set
-+# CONFIG_SND_DARLA24 is not set
-+# CONFIG_SND_GINA24 is not set
-+# CONFIG_SND_LAYLA24 is not set
-+# CONFIG_SND_MONA is not set
-+# CONFIG_SND_MIA is not set
-+# CONFIG_SND_ECHO3G is not set
-+# CONFIG_SND_INDIGO is not set
-+# CONFIG_SND_INDIGOIO is not set
-+# CONFIG_SND_INDIGODJ is not set
-+# CONFIG_SND_EMU10K1 is not set
-+# CONFIG_SND_EMU10K1X is not set
-+# CONFIG_SND_ENS1370 is not set
-+# CONFIG_SND_ENS1371 is not set
-+# CONFIG_SND_ES1938 is not set
-+# CONFIG_SND_ES1968 is not set
-+CONFIG_SND_FM801=y
-+# CONFIG_SND_FM801_TEA575X_BOOL is not set
-+# CONFIG_SND_HDA_INTEL is not set
-+# CONFIG_SND_HDSP is not set
-+# CONFIG_SND_HDSPM is not set
-+# CONFIG_SND_ICE1712 is not set
-+# CONFIG_SND_ICE1724 is not set
-+# CONFIG_SND_INTEL8X0 is not set
-+# CONFIG_SND_INTEL8X0M is not set
-+# CONFIG_SND_KORG1212 is not set
-+# CONFIG_SND_MAESTRO3 is not set
-+# CONFIG_SND_MIXART is not set
-+# CONFIG_SND_NM256 is not set
-+# CONFIG_SND_PCXHR is not set
-+# CONFIG_SND_RIPTIDE is not set
-+# CONFIG_SND_RME32 is not set
-+# CONFIG_SND_RME96 is not set
-+# CONFIG_SND_RME9652 is not set
-+# CONFIG_SND_SONICVIBES is not set
-+# CONFIG_SND_TRIDENT is not set
-+# CONFIG_SND_VIA82XX is not set
-+# CONFIG_SND_VIA82XX_MODEM is not set
-+# CONFIG_SND_VX222 is not set
-+# CONFIG_SND_YMFPCI is not set
-+
-+#
-+# USB devices
-+#
-+# CONFIG_SND_USB_AUDIO is not set
-+
-+#
-+# Open Sound System
-+#
-+CONFIG_SOUND_PRIME=y
-+# CONFIG_OSS_OBSOLETE_DRIVER is not set
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND is not set
+
+#
+# USB support
+#
-+CONFIG_USB_ARCH_HAS_HCD=y
-+CONFIG_USB_ARCH_HAS_OHCI=y
-+CONFIG_USB_ARCH_HAS_EHCI=y
-+CONFIG_USB=y
-+# CONFIG_USB_DEBUG is not set
-+
-+#
-+# Miscellaneous USB options
-+#
-+CONFIG_USB_DEVICEFS=y
-+CONFIG_USB_BANDWIDTH=y
-+# CONFIG_USB_DYNAMIC_MINORS is not set
-+# CONFIG_USB_SUSPEND is not set
-+# CONFIG_USB_OTG is not set
-+
-+#
-+# USB Host Controller Drivers
-+#
-+CONFIG_USB_EHCI_HCD=y
-+# CONFIG_USB_EHCI_SPLIT_ISO is not set
-+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
-+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-+# CONFIG_USB_ISP116X_HCD is not set
-+CONFIG_USB_OHCI_HCD=y
-+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
-+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-+CONFIG_USB_UHCI_HCD=y
-+# CONFIG_USB_SL811_HCD is not set
-+
-+#
-+# USB Device Class drivers
-+#
-+# CONFIG_USB_ACM is not set
-+# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_ARCH_HAS_HCD is not set
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
-+# may also be needed; see USB_STORAGE Help for more information
-+#
-+CONFIG_USB_STORAGE=y
-+# CONFIG_USB_STORAGE_DEBUG is not set
-+# CONFIG_USB_STORAGE_DATAFAB is not set
-+# CONFIG_USB_STORAGE_FREECOM is not set
-+# CONFIG_USB_STORAGE_ISD200 is not set
-+# CONFIG_USB_STORAGE_DPCM is not set
-+# CONFIG_USB_STORAGE_USBAT is not set
-+# CONFIG_USB_STORAGE_SDDR09 is not set
-+# CONFIG_USB_STORAGE_SDDR55 is not set
-+# CONFIG_USB_STORAGE_JUMPSHOT is not set
-+# CONFIG_USB_STORAGE_ALAUDA is not set
-+# CONFIG_USB_LIBUSUAL is not set
-+
-+#
-+# USB Input Devices
-+#
-+CONFIG_USB_HID=y
-+CONFIG_USB_HIDINPUT=y
-+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-+# CONFIG_HID_FF is not set
-+CONFIG_USB_HIDDEV=y
-+# CONFIG_USB_AIPTEK is not set
-+# CONFIG_USB_WACOM is not set
-+# CONFIG_USB_ACECAD is not set
-+# CONFIG_USB_KBTAB is not set
-+# CONFIG_USB_POWERMATE is not set
-+# CONFIG_USB_TOUCHSCREEN is not set
-+# CONFIG_USB_YEALINK is not set
-+# CONFIG_USB_XPAD is not set
-+# CONFIG_USB_ATI_REMOTE is not set
-+# CONFIG_USB_ATI_REMOTE2 is not set
-+# CONFIG_USB_KEYSPAN_REMOTE is not set
-+# CONFIG_USB_APPLETOUCH is not set
-+
-+#
-+# USB Imaging devices
-+#
-+# CONFIG_USB_MDC800 is not set
-+# CONFIG_USB_MICROTEK is not set
-+
-+#
-+# USB Network Adapters
-+#
-+# CONFIG_USB_CATC is not set
-+# CONFIG_USB_KAWETH is not set
-+# CONFIG_USB_PEGASUS is not set
-+# CONFIG_USB_RTL8150 is not set
-+# CONFIG_USB_USBNET is not set
-+CONFIG_USB_MON=y
-+
-+#
-+# USB port drivers
-+#
-+
-+#
-+# USB Serial Converter support
-+#
-+# CONFIG_USB_SERIAL is not set
-+
-+#
-+# USB Miscellaneous drivers
-+#
-+# CONFIG_USB_EMI62 is not set
-+# CONFIG_USB_EMI26 is not set
-+# CONFIG_USB_AUERSWALD is not set
-+# CONFIG_USB_RIO500 is not set
-+# CONFIG_USB_LEGOTOWER is not set
-+# CONFIG_USB_LCD is not set
-+# CONFIG_USB_LED is not set
-+# CONFIG_USB_CYPRESS_CY7C63 is not set
-+# CONFIG_USB_CYTHERM is not set
-+# CONFIG_USB_PHIDGETKIT is not set
-+# CONFIG_USB_PHIDGETSERVO is not set
-+# CONFIG_USB_IDMOUSE is not set
-+# CONFIG_USB_APPLEDISPLAY is not set
-+# CONFIG_USB_SISUSBVGA is not set
-+# CONFIG_USB_LD is not set
-+# CONFIG_USB_TEST is not set
-+
-+#
-+# USB DSL modem support
-+#
-+
-+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
@@ -66226,11 +66679,11 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# InfiniBand support
+#
-+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
++# CONFIG_EDAC is not set
+
+#
+# Real Time Clock
@@ -66251,33 +66704,32 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+
+#
++# Firmware Drivers
++#
++# CONFIG_EDD is not set
++# CONFIG_DELL_RBU is not set
++# CONFIG_DCDBAS is not set
++
++#
+# File systems
+#
+CONFIG_EXT2_FS=y
-+CONFIG_EXT2_FS_XATTR=y
-+CONFIG_EXT2_FS_POSIX_ACL=y
-+CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
-+CONFIG_EXT3_FS_POSIX_ACL=y
-+CONFIG_EXT3_FS_SECURITY=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
-+CONFIG_REISERFS_FS_XATTR=y
-+CONFIG_REISERFS_FS_POSIX_ACL=y
-+CONFIG_REISERFS_FS_SECURITY=y
++# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
-+CONFIG_FS_POSIX_ACL=y
-+CONFIG_XFS_FS=y
-+# CONFIG_XFS_QUOTA is not set
-+# CONFIG_XFS_SECURITY is not set
-+# CONFIG_XFS_POSIX_ACL is not set
-+# CONFIG_XFS_RT is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
@@ -66294,16 +66746,16 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
-+# CONFIG_ZISOFS is not set
-+CONFIG_UDF_FS=y
-+CONFIG_UDF_NLS=y
++CONFIG_ZISOFS=y
++CONFIG_ZISOFS_FS=y
++# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
-+CONFIG_FAT_FS=y
-+CONFIG_MSDOS_FS=y
-+CONFIG_VFAT_FS=y
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
@@ -66313,7 +66765,6 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
-+CONFIG_PROC_IOMEM_MACHINE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
@@ -66330,7 +66781,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
-+# CONFIG_CRAMFS is not set
++CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
@@ -66343,31 +66794,18 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
-+CONFIG_NFS_V4=y
-+CONFIG_NFS_DIRECTIO=y
-+CONFIG_NFSD=y
-+CONFIG_NFSD_V3=y
-+# CONFIG_NFSD_V3_ACL is not set
-+CONFIG_NFSD_V4=y
-+CONFIG_NFSD_TCP=y
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
-+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
-+CONFIG_SUNRPC_GSS=y
-+CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
-+CONFIG_SMB_FS=y
-+CONFIG_SMB_NLS_DEFAULT=y
-+CONFIG_SMB_NLS_REMOTE="cp437"
-+CONFIG_CIFS=y
-+# CONFIG_CIFS_STATS is not set
-+# CONFIG_CIFS_WEAK_PW_HASH is not set
-+# CONFIG_CIFS_XATTR is not set
-+# CONFIG_CIFS_DEBUG2 is not set
-+# CONFIG_CIFS_EXPERIMENTAL is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
@@ -66376,23 +66814,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# Partition Types
+#
-+CONFIG_PARTITION_ADVANCED=y
-+# CONFIG_ACORN_PARTITION is not set
-+# CONFIG_OSF_PARTITION is not set
-+# CONFIG_AMIGA_PARTITION is not set
-+# CONFIG_ATARI_PARTITION is not set
-+# CONFIG_MAC_PARTITION is not set
++# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_BSD_DISKLABEL is not set
-+# CONFIG_MINIX_SUBPARTITION is not set
-+# CONFIG_SOLARIS_X86_PARTITION is not set
-+# CONFIG_UNIXWARE_DISKLABEL is not set
-+# CONFIG_LDM_PARTITION is not set
-+CONFIG_SGI_PARTITION=y
-+# CONFIG_ULTRIX_PARTITION is not set
-+# CONFIG_SUN_PARTITION is not set
-+# CONFIG_KARMA_PARTITION is not set
-+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
@@ -66400,63 +66823,43 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_CODEPAGE_737=y
-+CONFIG_NLS_CODEPAGE_775=y
-+CONFIG_NLS_CODEPAGE_850=y
-+CONFIG_NLS_CODEPAGE_852=y
-+CONFIG_NLS_CODEPAGE_855=y
-+CONFIG_NLS_CODEPAGE_857=y
-+CONFIG_NLS_CODEPAGE_860=y
-+CONFIG_NLS_CODEPAGE_861=y
-+CONFIG_NLS_CODEPAGE_862=y
-+CONFIG_NLS_CODEPAGE_863=y
-+CONFIG_NLS_CODEPAGE_864=y
-+CONFIG_NLS_CODEPAGE_865=y
-+CONFIG_NLS_CODEPAGE_866=y
-+CONFIG_NLS_CODEPAGE_869=y
-+CONFIG_NLS_CODEPAGE_936=y
-+CONFIG_NLS_CODEPAGE_950=y
-+CONFIG_NLS_CODEPAGE_932=y
-+CONFIG_NLS_CODEPAGE_949=y
-+CONFIG_NLS_CODEPAGE_874=y
-+CONFIG_NLS_ISO8859_8=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
-+CONFIG_NLS_CODEPAGE_1251=y
++# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
-+CONFIG_NLS_ISO8859_2=y
-+CONFIG_NLS_ISO8859_3=y
-+CONFIG_NLS_ISO8859_4=y
-+CONFIG_NLS_ISO8859_5=y
-+CONFIG_NLS_ISO8859_6=y
-+CONFIG_NLS_ISO8859_7=y
-+CONFIG_NLS_ISO8859_9=y
-+CONFIG_NLS_ISO8859_13=y
-+CONFIG_NLS_ISO8859_14=y
-+CONFIG_NLS_ISO8859_15=y
-+CONFIG_NLS_KOI8_R=y
-+CONFIG_NLS_KOI8_U=y
-+CONFIG_NLS_UTF8=y
-+
-+#
-+# Library routines
-+#
-+# CONFIG_CRC_CCITT is not set
-+# CONFIG_CRC16 is not set
-+CONFIG_CRC32=y
-+# CONFIG_LIBCRC32C is not set
-+CONFIG_PLIST=y
-+CONFIG_GENERIC_HARDIRQS=y
-+CONFIG_GENERIC_IRQ_PROBE=y
-+CONFIG_GENERIC_PENDING_IRQ=y
-+CONFIG_IRQ_PER_CPU=y
-+
-+#
-+# HP Simulator drivers
-+#
-+# CONFIG_HP_SIMETH is not set
-+# CONFIG_HP_SIMSERIAL is not set
-+# CONFIG_HP_SIMSCSI is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
@@ -66467,33 +66870,35 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+#
+# Kernel hacking
+#
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_KERNEL=y
-+CONFIG_LOG_BUF_SHIFT=20
++CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
-+CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
-+# CONFIG_DEBUG_INFO is not set
++CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
-+CONFIG_IA64_GRANULE_16MB=y
-+# CONFIG_IA64_GRANULE_64MB is not set
-+CONFIG_IA64_PRINT_HAZARDS=y
-+# CONFIG_DISABLE_VHPT is not set
-+# CONFIG_IA64_DEBUG_CMPXCHG is not set
-+# CONFIG_IA64_DEBUG_IRQ is not set
++# CONFIG_DEBUG_RODATA is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
+
+#
+# Security options
@@ -66508,17 +66913,18 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
-+CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_MD5=m
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
-+CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_AES_X86_64 is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
@@ -66527,42 +66933,30 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
-+# CONFIG_CRYPTO_CRC32C is not set
++CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
-+# CONFIG_XEN_SMPBOOT is not set
-+# CONFIG_XEN_DEVMEM is not set
++CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
+
+#
+# XEN
+#
-+CONFIG_XEN_PRIVILEGED_GUEST=y
-+# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
++# CONFIG_XEN_PRIVILEGED_GUEST is not set
++CONFIG_XEN_UNPRIVILEGED_GUEST=y
+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 is not set
-+CONFIG_XEN_PCIDEV_BACKEND=y
-+# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
-+# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
-+# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
-+CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER=y
-+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
-+CONFIG_XEN_TPMDEV_BACKEND=m
++# CONFIG_XEN_BACKEND is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
++CONFIG_XEN_SCSI_FRONTEND=m
+CONFIG_XEN_GRANT_DEV=y
-+CONFIG_XEN_FRAMEBUFFER=y
-+CONFIG_XEN_KEYBOARD=y
-+# CONFIG_XEN_SCRUB_PAGES is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
++CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
@@ -66572,12 +66966,23 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_ia64 linux-2.6.18-xen
+CONFIG_XEN_COMPAT=0x030002
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
++CONFIG_XEN_SMPBOOT=y
+CONFIG_XEN_BALLOON=y
-+CONFIG_XEN_XENCOMM=y
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen_x86_32
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen_x86_32 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,3318 @@
++CONFIG_XEN_DEVMEM=y
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC32 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen_x86_32
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen_x86_32 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,3326 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
@@ -66834,6 +67239,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-x
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+# CONFIG_PCIEPORTBUS is not set
++# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_SCx200=m
@@ -67856,6 +68262,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-x
+CONFIG_I2O=m
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
++CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
@@ -67998,6 +68405,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-x
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
++# CONFIG_SFC is not set
+
+#
+# Token Ring devices
@@ -69829,7 +70237,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-x
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+CONFIG_XEN=y
-+CONFIG_XEN_INTERFACE_VERSION=0x00030206
++CONFIG_XEN_INTERFACE_VERSION=0x00030207
+
+#
+# XEN
@@ -69843,6 +70251,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-x
+CONFIG_XEN_BLKDEV_TAP=y
+CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
+# CONFIG_XEN_NETDEV_LOOPBACK is not set
+CONFIG_XEN_PCIDEV_BACKEND=m
+CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
@@ -69851,10 +70261,13 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-x
+# CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
+CONFIG_XEN_TPMDEV_BACKEND=m
++CONFIG_XEN_SCSI_BACKEND=m
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
-+CONFIG_XEN_FRAMEBUFFER=y
++CONFIG_XEN_SCSI_FRONTEND=m
+CONFIG_XEN_GRANT_DEV=y
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
++CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
@@ -69896,14 +70309,14 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_32 linux-2.6.18-x
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
+CONFIG_KTIME_SCALAR=y
-diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen_x86_64
---- linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/buildconfigs/linux-defconfig_xen_x86_64 2008-02-15 16:21:56.000000000 -0800
-@@ -0,0 +1,3139 @@
+diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen_x86_64
+--- linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/buildconfigs/linux-defconfig_xen_x86_64 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,3146 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.8
-+# Tue Oct 16 09:32:25 2007
++# Mon Feb 18 10:38:24 2008
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
@@ -70111,6 +70524,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 linux-2.6.18-x
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+# CONFIG_PCIEPORTBUS is not set
++# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
@@ -71260,6 +71674,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 linux-2.6.18-x
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
++# CONFIG_SFC is not set
+
+#
+# Token Ring devices
@@ -72982,7 +73397,7 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 linux-2.6.18-x
+# Hardware crypto devices
+#
+CONFIG_XEN=y
-+CONFIG_XEN_INTERFACE_VERSION=0x00030206
++CONFIG_XEN_INTERFACE_VERSION=0x00030207
+
+#
+# XEN
@@ -72996,6 +73411,8 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 linux-2.6.18-x
+CONFIG_XEN_BLKDEV_TAP=y
+CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
++# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
+# CONFIG_XEN_NETDEV_LOOPBACK is not set
+CONFIG_XEN_PCIDEV_BACKEND=m
+# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
@@ -73004,10 +73421,13 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 linux-2.6.18-x
+# CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
+CONFIG_XEN_TPMDEV_BACKEND=m
++CONFIG_XEN_SCSI_BACKEND=m
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
-+CONFIG_XEN_FRAMEBUFFER=y
++CONFIG_XEN_SCSI_FRONTEND=m
+CONFIG_XEN_GRANT_DEV=y
++# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
++CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
@@ -73039,20 +73459,191 @@ diff -rpuN linux-2.6.18.8/buildconfigs/linux-defconfig_xen_x86_64 linux-2.6.18-x
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
-diff -rpuN linux-2.6.18.8/drivers/Makefile linux-2.6.18-xen-3.2.0/drivers/Makefile
---- linux-2.6.18.8/drivers/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/Makefile 2008-02-15 16:21:56.000000000 -0800
-@@ -31,6 +31,7 @@ obj-y += base/ block/ misc/ mfd/ net/
- obj-$(CONFIG_NUBUS) += nubus/
- obj-$(CONFIG_ATM) += atm/
- obj-$(CONFIG_PPC_PMAC) += macintosh/
-+obj-$(CONFIG_XEN) += xen/
- obj-$(CONFIG_IDE) += ide/
- obj-$(CONFIG_FC4) += fc4/
- obj-$(CONFIG_SCSI) += scsi/
-diff -rpuN linux-2.6.18.8/drivers/acpi/Kconfig linux-2.6.18-xen-3.2.0/drivers/acpi/Kconfig
---- linux-2.6.18.8/drivers/acpi/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/acpi/Kconfig 2008-02-15 16:21:56.000000000 -0800
+diff -rpuN linux-2.6.18.8/Documentation/i2c/busses/i2c-i801 linux-2.6.18-xen-3.3.0/Documentation/i2c/busses/i2c-i801
+--- linux-2.6.18.8/Documentation/i2c/busses/i2c-i801 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/Documentation/i2c/busses/i2c-i801 2008-08-21 11:36:07.000000000 +0200
+@@ -10,6 +10,11 @@ Supported adapters:
+ * Intel 6300ESB
+ * Intel 82801FB/FR/FW/FRW (ICH6)
+ * Intel ICH7
++ * Intel 82801G (ICH7)
++ * Intel 82801H (ICH9)
++ * Intel 82801I (ICH9)
++ * Intel Tolapai
++ * Intel ICH10
+ Datasheets: Publicly available at the Intel website
+
+ Authors:
+diff -rpuN linux-2.6.18.8/drivers/acpi/dispatcher/dsobject.c linux-2.6.18-xen-3.3.0/drivers/acpi/dispatcher/dsobject.c
+--- linux-2.6.18.8/drivers/acpi/dispatcher/dsobject.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/dispatcher/dsobject.c 2008-08-21 11:36:07.000000000 +0200
+@@ -137,6 +137,71 @@ acpi_ds_build_internal_object(struct acp
+ return_ACPI_STATUS(status);
+ }
+ }
++
++ /* Special object resolution for elements of a package */
++
++ if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
++ (op->common.parent->common.aml_opcode ==
++ AML_VAR_PACKAGE_OP)) {
++ /*
++ * Attempt to resolve the node to a value before we insert it into
++ * the package. If this is a reference to a common data type,
++ * resolve it immediately. According to the ACPI spec, package
++ * elements can only be "data objects" or method references.
++ * Attempt to resolve to an Integer, Buffer, String or Package.
++ * If cannot, return the named reference (for things like Devices,
++ * Methods, etc.) Buffer Fields and Fields will resolve to simple
++ * objects (int/buf/str/pkg).
++ *
++ * NOTE: References to things like Devices, Methods, Mutexes, etc.
++ * will remain as named references. This behavior is not described
++ * in the ACPI spec, but it appears to be an oversight.
++ */
++ obj_desc = (union acpi_operand_object *)op->common.node;
++
++ status =
++ acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
++ (struct
++ acpi_namespace_node,
++ &obj_desc),
++ walk_state);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ switch (op->common.node->type) {
++ /*
++ * For these types, we need the actual node, not the subobject.
++ * However, the subobject got an extra reference count above.
++ */
++ case ACPI_TYPE_MUTEX:
++ case ACPI_TYPE_METHOD:
++ case ACPI_TYPE_POWER:
++ case ACPI_TYPE_PROCESSOR:
++ case ACPI_TYPE_EVENT:
++ case ACPI_TYPE_REGION:
++ case ACPI_TYPE_DEVICE:
++ case ACPI_TYPE_THERMAL:
++
++ obj_desc =
++ (union acpi_operand_object *)op->common.
++ node;
++ break;
++
++ default:
++ break;
++ }
++
++ /*
++ * If above resolved to an operand object, we are done. Otherwise,
++ * we have a NS node, we must create the package entry as a named
++ * reference.
++ */
++ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
++ ACPI_DESC_TYPE_NAMED) {
++ goto exit;
++ }
++ }
+ }
+
+ /* Create and init a new internal ACPI object */
+@@ -156,6 +221,7 @@ acpi_ds_build_internal_object(struct acp
+ return_ACPI_STATUS(status);
+ }
+
++ exit:
+ *obj_desc_ptr = obj_desc;
+ return_ACPI_STATUS(AE_OK);
+ }
+@@ -358,12 +424,25 @@ acpi_ds_build_internal_package_obj(struc
+ arg = arg->common.next;
+ for (i = 0; arg; i++) {
+ if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
+-
+- /* Object (package or buffer) is already built */
+-
+- obj_desc->package.elements[i] =
+- ACPI_CAST_PTR(union acpi_operand_object,
+- arg->common.node);
++ if (arg->common.node->type == ACPI_TYPE_METHOD) {
++ /*
++ * A method reference "looks" to the parser to be a method
++ * invocation, so we special case it here
++ */
++ arg->common.aml_opcode = AML_INT_NAMEPATH_OP;
++ status =
++ acpi_ds_build_internal_object(walk_state,
++ arg,
++ &obj_desc->
++ package.
++ elements[i]);
++ } else {
++ /* This package element is already built, just get it */
++
++ obj_desc->package.elements[i] =
++ ACPI_CAST_PTR(union acpi_operand_object,
++ arg->common.node);
++ }
+ } else {
+ status = acpi_ds_build_internal_object(walk_state, arg,
+ &obj_desc->
+diff -rpuN linux-2.6.18.8/drivers/acpi/hardware/hwregs.c linux-2.6.18-xen-3.3.0/drivers/acpi/hardware/hwregs.c
+--- linux-2.6.18.8/drivers/acpi/hardware/hwregs.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/hardware/hwregs.c 2008-08-21 11:36:07.000000000 +0200
+@@ -665,8 +665,6 @@ acpi_status acpi_hw_register_write(u8 us
+
+ /*
+ * Perform a read first to preserve certain bits (per ACPI spec)
+- *
+- * Note: This includes SCI_EN, we never want to change this bit
+ */
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL,
+diff -rpuN linux-2.6.18.8/drivers/acpi/hardware/hwsleep.c linux-2.6.18-xen-3.3.0/drivers/acpi/hardware/hwsleep.c
+--- linux-2.6.18.8/drivers/acpi/hardware/hwsleep.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/hardware/hwsleep.c 2008-08-21 11:36:07.000000000 +0200
+@@ -227,7 +227,11 @@ acpi_status asmlinkage acpi_enter_sleep_
+ u32 PM1Bcontrol;
+ struct acpi_bit_register_info *sleep_type_reg_info;
+ struct acpi_bit_register_info *sleep_enable_reg_info;
++#if !(defined(CONFIG_XEN) && defined(CONFIG_X86))
+ u32 in_value;
++#else
++ int err;
++#endif
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
+@@ -327,6 +331,7 @@ acpi_status asmlinkage acpi_enter_sleep_
+
+ ACPI_FLUSH_CPU_CACHE();
+
++#if !(defined(CONFIG_XEN) && defined(CONFIG_X86))
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL,
+ PM1Acontrol);
+@@ -376,6 +381,16 @@ acpi_status asmlinkage acpi_enter_sleep_
+ /* Spin until we wake */
+
+ } while (!in_value);
++#else
++ /* PV ACPI just need check hypercall return value */
++ err = acpi_notify_hypervisor_state(sleep_state,
++ PM1Acontrol, PM1Bcontrol);
++ if (err) {
++ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
++ "Hypervisor failure [%d]\n", err));
++ return_ACPI_STATUS(AE_ERROR);
++ }
++#endif
+
+ return_ACPI_STATUS(AE_OK);
+ }
+diff -rpuN linux-2.6.18.8/drivers/acpi/Kconfig linux-2.6.18-xen-3.3.0/drivers/acpi/Kconfig
+--- linux-2.6.18.8/drivers/acpi/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/Kconfig 2008-08-21 11:36:07.000000000 +0200
@@ -305,6 +305,7 @@ config ACPI_SYSTEM
config X86_PM_TIMER
bool "Power Management Timer Support" if EMBEDDED
@@ -73061,7 +73652,7 @@ diff -rpuN linux-2.6.18.8/drivers/acpi/Kconfig linux-2.6.18-xen-3.2.0/drivers/ac
default y
help
The Power Management Timer is available on all ACPI-capable,
-@@ -362,6 +363,10 @@ config ACPI_SBS
+@@ -362,6 +363,15 @@ config ACPI_SBS
A "Smart Battery" is quite old and quite rare compared
to today's ACPI "Control Method" battery.
@@ -73069,39 +73660,599 @@ diff -rpuN linux-2.6.18.8/drivers/acpi/Kconfig linux-2.6.18-xen-3.2.0/drivers/ac
+ bool
+ depends on X86 && XEN && ACPI_SLEEP
+ default y
++
++config PROCESSOR_EXTERNAL_CONTROL
++ bool
++ depends on X86 && XEN
++ default y
endif # ACPI
endmenu
-diff -rpuN linux-2.6.18.8/drivers/acpi/hardware/hwsleep.c linux-2.6.18-xen-3.2.0/drivers/acpi/hardware/hwsleep.c
---- linux-2.6.18.8/drivers/acpi/hardware/hwsleep.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/acpi/hardware/hwsleep.c 2008-02-15 16:21:57.000000000 -0800
-@@ -327,6 +327,7 @@ acpi_status asmlinkage acpi_enter_sleep_
+diff -rpuN linux-2.6.18.8/drivers/acpi/Makefile linux-2.6.18-xen-3.3.0/drivers/acpi/Makefile
+--- linux-2.6.18.8/drivers/acpi/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -34,6 +34,9 @@ processor-objs += processor_core.o proce
+ ifdef CONFIG_CPU_FREQ
+ processor-objs += processor_perflib.o
+ endif
++ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++processor-objs += processor_perflib.o processor_extcntl.o
++endif
- ACPI_FLUSH_CPU_CACHE();
+ obj-y += sleep/
+ obj-y += bus.o glue.o
+diff -rpuN linux-2.6.18.8/drivers/acpi/processor_core.c linux-2.6.18-xen-3.3.0/drivers/acpi/processor_core.c
+--- linux-2.6.18.8/drivers/acpi/processor_core.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/processor_core.c 2008-08-21 11:36:07.000000000 +0200
+@@ -475,7 +475,8 @@ static int acpi_processor_get_info(struc
+ */
+ if (cpu_index == -1) {
+ if (ACPI_FAILURE
+- (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
++ (acpi_processor_hotadd_init(pr->handle, &pr->id)) &&
++ !processor_cntl_external()) {
+ printk(KERN_ERR PREFIX
+ "Getting cpuindex for acpiid 0x%x\n",
+ pr->acpi_id);
+@@ -508,7 +509,7 @@ static int acpi_processor_get_info(struc
+ request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+ }
-+#ifndef CONFIG_ACPI_PV_SLEEP
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL,
- PM1Acontrol);
-@@ -378,6 +379,15 @@ acpi_status asmlinkage acpi_enter_sleep_
- } while (!in_value);
+-#ifdef CONFIG_CPU_FREQ
++#if defined(CONFIG_CPU_FREQ) || defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
+ acpi_processor_ppc_has_changed(pr);
+ #endif
+ acpi_processor_get_throttling_info(pr);
+@@ -517,7 +518,7 @@ static int acpi_processor_get_info(struc
+ return 0;
+ }
- return_ACPI_STATUS(AE_OK);
+-static void *processor_device_array[NR_CPUS];
++static void *processor_device_array[NR_ACPI_CPUS];
+
+ static int acpi_processor_start(struct acpi_device *device)
+ {
+@@ -525,31 +526,46 @@ static int acpi_processor_start(struct a
+ acpi_status status = AE_OK;
+ struct acpi_processor *pr;
+
++ processor_extcntl_init();
+
+ pr = acpi_driver_data(device);
+
+ result = acpi_processor_get_info(pr);
+- if (result) {
++ if (result ||
++ ((pr->id == -1) && !processor_cntl_external())) {
+ /* Processor is physically not present */
+ return 0;
+ }
+
+- BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0));
++ BUG_ON(!processor_cntl_external() &&
++ ((pr->id >= NR_CPUS) || (pr->id < 0)));
+
+ /*
+ * Buggy BIOS check
+ * ACPI id of processors can be reported wrongly by the BIOS.
+ * Don't trust it blindly
+ */
++#ifdef CONFIG_XEN
++ BUG_ON(pr->acpi_id >= NR_ACPI_CPUS);
++ if (processor_device_array[pr->acpi_id] != NULL &&
++ processor_device_array[pr->acpi_id] != (void *)device) {
+#else
-+ /* PV ACPI just need check hypercall return value */
-+ status = acpi_notify_hypervisor_state(sleep_state,
-+ PM1Acontrol, PM1Bcontrol);
-+ if (ACPI_FAILURE(status))
-+ return_ACPI_STATUS(status);
-+ else
-+ return_ACPI_STATUS(AE_OK);
+ if (processor_device_array[pr->id] != NULL &&
+ processor_device_array[pr->id] != (void *)device) {
++#endif /* CONFIG_XEN */
+ printk(KERN_WARNING "BIOS reported wrong ACPI id"
+ "for the processor\n");
+ return -ENODEV;
+ }
++#ifdef CONFIG_XEN
++ processor_device_array[pr->acpi_id] = (void *)device;
++ if (pr->id != -1)
++ processors[pr->id] = pr;
++#else
+ processor_device_array[pr->id] = (void *)device;
+
+ processors[pr->id] = pr;
++#endif /* CONFIG_XEN */
+
+ result = acpi_processor_add_fs(device);
+ if (result)
+@@ -564,6 +580,10 @@ static int acpi_processor_start(struct a
+
+ acpi_processor_power_init(pr, device);
+
++ result = processor_extcntl_prepare(pr);
++ if (result)
++ goto end;
++
+ if (pr->flags.throttling) {
+ printk(KERN_INFO PREFIX "%s [%s] (supports",
+ acpi_device_name(device), acpi_device_bid(device));
+@@ -656,7 +676,13 @@ static int acpi_processor_remove(struct
+
+ acpi_processor_remove_fs(device);
+
++#ifdef CONFIG_XEN
++ if (pr->id != -1)
++ processors[pr->id] = NULL;
++#else
+ processors[pr->id] = NULL;
++#endif /* CONFIG_XEN */
++
+
+ kfree(pr);
+
+@@ -710,6 +736,10 @@ int acpi_processor_device_add(acpi_handl
+ if (!pr)
+ return -ENODEV;
+
++ if (processor_cntl_external())
++ processor_notify_external(pr,
++ PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
++
+ if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
+ kobject_uevent(&(*device)->kobj, KOBJ_ONLINE);
+ }
+@@ -748,6 +778,10 @@ acpi_processor_hotplug_notify(acpi_handl
+ break;
+ }
+
++ if (processor_cntl_external())
++ processor_notify_external(pr,
++ PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
++
+ if (pr->id >= 0 && (pr->id < NR_CPUS)) {
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
+ break;
+@@ -777,8 +811,18 @@ acpi_processor_hotplug_notify(acpi_handl
+ return;
+ }
+
++#ifdef CONFIG_XEN
++ if ((pr->id >= 0) && (pr->id < NR_CPUS)
++ && (cpu_present(pr->id)))
++#else
+ if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
++#endif /* CONFIG_XEN */
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
++
++ if (processor_cntl_external())
++ processor_notify_external(pr, PROCESSOR_HOTPLUG,
++ HOTPLUG_TYPE_REMOVE);
++
+ break;
+ default:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+@@ -843,6 +887,11 @@ static acpi_status acpi_processor_hotadd
+
+ static int acpi_processor_handle_eject(struct acpi_processor *pr)
+ {
++#ifdef CONFIG_XEN
++ if (pr->id == -1)
++ return (0);
++#endif /* CONFIG_XEN */
++
+ if (cpu_online(pr->id)) {
+ return (-EINVAL);
+ }
+diff -rpuN linux-2.6.18.8/drivers/acpi/processor_extcntl.c linux-2.6.18-xen-3.3.0/drivers/acpi/processor_extcntl.c
+--- linux-2.6.18.8/drivers/acpi/processor_extcntl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/processor_extcntl.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,232 @@
++/*
++ * processor_extcntl.c - channel to external control logic
++ *
++ * Copyright (C) 2008, Intel corporation
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * 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; either version 2 of the License, or (at
++ * your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/acpi.h>
++#include <linux/pm.h>
++#include <linux/cpu.h>
++
++#include <acpi/processor.h>
++
++#define ACPI_PROCESSOR_COMPONENT 0x01000000
++#define ACPI_PROCESSOR_CLASS "processor"
++#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
++#define _COMPONENT ACPI_PROCESSOR_COMPONENT
++ACPI_MODULE_NAME("acpi_processor")
++
++static int processor_extcntl_parse_csd(struct acpi_processor *pr);
++static int processor_extcntl_get_performance(struct acpi_processor *pr);
++/*
++ * External processor control logic may register with its own set of
++ * ops to get ACPI related notification. One example is like VMM.
++ */
++const struct processor_extcntl_ops *processor_extcntl_ops;
++EXPORT_SYMBOL(processor_extcntl_ops);
++
++static int processor_notify_smm(void)
++{
++ acpi_status status;
++ static int is_done = 0;
++
++ /* only need successfully notify BIOS once */
++ /* avoid double notification which may lead to unexpected result */
++ if (is_done)
++ return 0;
++
++ /* Can't write pstate_cnt to smi_cmd if either value is zero */
++ if ((!acpi_fadt.smi_cmd) || (!acpi_fadt.pstate_cnt)) {
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"No SMI port or pstate_cnt\n"));
++ return 0;
++ }
++
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++ "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n",
++ acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
++
++ /* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
++ * it anyway, so we need to support it... */
++ if (acpi_fadt_is_v1) {
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++ "Using v1.0 FADT reserved value for pstate_cnt\n"));
++ }
++
++ status = acpi_os_write_port(acpi_fadt.smi_cmd,
++ (u32) acpi_fadt.pstate_cnt, 8);
++ if (ACPI_FAILURE(status))
++ return status;
++
++ is_done = 1;
++
++ return 0;
++}
++
++int processor_notify_external(struct acpi_processor *pr, int event, int type)
++{
++ int ret = -EINVAL;
++
++ if (!processor_cntl_external())
++ return -EINVAL;
++
++ switch (event) {
++ case PROCESSOR_PM_INIT:
++ case PROCESSOR_PM_CHANGE:
++ if ((type >= PM_TYPE_MAX) ||
++ !processor_extcntl_ops->pm_ops[type])
++ break;
++
++ ret = processor_extcntl_ops->pm_ops[type](pr, event);
++ break;
++ case PROCESSOR_HOTPLUG:
++ if (processor_extcntl_ops->hotplug)
++ ret = processor_extcntl_ops->hotplug(pr, type);
++ break;
++ default:
++ printk(KERN_ERR "Unsupport processor events %d.\n", event);
++ break;
++ }
++
++ return ret;
++}
++
++/*
++ * External control logic can decide to grab full or part of physical
++ * processor control bits. Take a VMM for example, physical processors
++ * are owned by VMM and thus existence information like hotplug is
++ * always required to be notified to VMM. Similar is processor idle
++ * state which is also necessarily controlled by VMM. But for other
++ * control bits like performance/throttle states, VMM may choose to
++ * control or not upon its own policy.
++ */
++void processor_extcntl_init(void)
++{
++ if (!processor_extcntl_ops)
++ arch_acpi_processor_init_extcntl(&processor_extcntl_ops);
++}
++
++/*
++ * This is called from ACPI processor init, and targeted to hold
++ * some tricky housekeeping jobs to satisfy external control model.
++ * For example, we may put dependency parse stub here for idle
++ * and performance state. Those information may be not available
++ * if splitting from dom0 control logic like cpufreq driver.
++ */
++int processor_extcntl_prepare(struct acpi_processor *pr)
++{
++ /* parse cstate dependency information */
++ if (processor_pm_external())
++ processor_extcntl_parse_csd(pr);
++
++ /* Initialize performance states */
++ if (processor_pmperf_external())
++ processor_extcntl_get_performance(pr);
++
++ return 0;
++}
++
++/*
++ * Currently no _CSD is implemented which is why existing ACPI code
++ * doesn't parse _CSD at all. But to keep interface complete with
++ * external control logic, we put a placeholder here for future
++ * compatibility.
++ */
++static int processor_extcntl_parse_csd(struct acpi_processor *pr)
++{
++ int i;
++
++ for (i = 0; i < pr->power.count; i++) {
++ if (!pr->power.states[i].valid)
++ continue;
++
++ /* No dependency by default */
++ pr->power.states[i].domain_info = NULL;
++ pr->power.states[i].csd_count = 0;
++ }
++
++ return 0;
++}
++
++/*
++ * Existing ACPI module does parse performance states at some point,
++ * when acpi-cpufreq driver is loaded which however is something
++ * we'd like to disable to avoid confliction with external control
++ * logic. So we have to collect raw performance information here
++ * when ACPI processor object is found and started.
++ */
++static int processor_extcntl_get_performance(struct acpi_processor *pr)
++{
++ int ret;
++ struct acpi_processor_performance *perf;
++ struct acpi_psd_package *pdomain;
++
++ if (pr->performance)
++ return -EBUSY;
++
++ perf = kzalloc(sizeof(struct acpi_processor_performance), GFP_KERNEL);
++ if (!perf)
++ return -ENOMEM;
++
++ pr->performance = perf;
++ /* Get basic performance state information */
++ ret = acpi_processor_get_performance_info(pr);
++ if (ret < 0)
++ goto err_out;
++
++ /*
++ * Well, here we need retrieve performance dependency information
++ * from _PSD object. The reason why existing interface is not used
++ * is due to the reason that existing interface sticks to Linux cpu
++ * id to construct some bitmap, however we want to split ACPI
++ * processor objects from Linux cpu id logic. For example, even
++ * when Linux is configured as UP, we still want to parse all ACPI
++ * processor objects to external logic. In this case, it's preferred
++ * to use ACPI ID instead.
++ */
++ pr->performance->domain_info.num_processors = 0;
++ ret = acpi_processor_get_psd(pr);
++ if (ret < 0)
++ goto err_out;
++
++ /* Some sanity check */
++ pdomain = &pr->performance->domain_info;
++ if ((pdomain->revision != ACPI_PSD_REV0_REVISION) ||
++ (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) ||
++ ((pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL) &&
++ (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY) &&
++ (pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL))) {
++ ret = -EINVAL;
++ goto err_out;
++ }
++
++ /* Last step is to notify BIOS that external logic exists */
++ processor_notify_smm();
++
++ processor_notify_external(pr, PROCESSOR_PM_INIT, PM_TYPE_PERF);
++
++ return 0;
++err_out:
++ pr->performance = NULL;
++ kfree(perf);
++ return ret;
++}
+diff -rpuN linux-2.6.18.8/drivers/acpi/processor_idle.c linux-2.6.18-xen-3.3.0/drivers/acpi/processor_idle.c
+--- linux-2.6.18.8/drivers/acpi/processor_idle.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/processor_idle.c 2008-08-21 11:36:07.000000000 +0200
+@@ -714,8 +714,12 @@ static int acpi_processor_get_power_info
+ (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
+ continue;
+
+- cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
+- 0 : reg->address;
++ if (!processor_pm_external())
++ cx.address = (reg->space_id ==
++ ACPI_ADR_SPACE_FIXED_HARDWARE) ?
++ 0 : reg->address;
++ else
++ cx.address = reg->address;
+
+ /* There should be an easy way to extract an integer... */
+ obj = (union acpi_object *)&(element->package.elements[1]);
+@@ -724,7 +728,9 @@ static int acpi_processor_get_power_info
+
+ cx.type = obj->integer.value;
+
+- if ((cx.type != ACPI_STATE_C1) &&
++ /* Following check doesn't apply to external control case */
++ if (!processor_pm_external() &&
++ (cx.type != ACPI_STATE_C1) &&
+ (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
+ continue;
+
+@@ -743,6 +749,12 @@ static int acpi_processor_get_power_info
+
+ cx.power = obj->integer.value;
+
++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++ /* cache control methods to notify external logic */
++ if (processor_pm_external())
++ memcpy(&cx.reg, reg, sizeof(*reg));
++#endif
++
+ current_count++;
+ memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
+
+@@ -985,12 +997,16 @@ int acpi_processor_cst_has_changed(struc
+ return -ENODEV;
+
+ /* Fall back to the default idle loop */
+- pm_idle = pm_idle_save;
++ if (!processor_pm_external())
++ pm_idle = pm_idle_save;
+ synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
+
+ pr->flags.power = 0;
+ result = acpi_processor_get_power_info(pr);
+- if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
++ if (processor_pm_external())
++ processor_notify_external(pr,
++ PROCESSOR_PM_CHANGE, PM_TYPE_IDLE);
++ else if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
+ pm_idle = acpi_processor_idle;
+
+ return result;
+@@ -1122,7 +1138,7 @@ int acpi_processor_power_init(struct acp
+ pr->power.states[i].type);
+ printk(")\n");
+
+- if (pr->id == 0) {
++ if (!processor_pm_external() && (pr->id == 0)) {
+ pm_idle_save = pm_idle;
+ pm_idle = acpi_processor_idle;
+ }
+@@ -1141,6 +1157,9 @@ int acpi_processor_power_init(struct acp
+
+ pr->flags.power_setup_done = 1;
+
++ if (processor_pm_external())
++ processor_notify_external(pr,
++ PROCESSOR_PM_INIT, PM_TYPE_IDLE);
+ return 0;
+ }
+
+diff -rpuN linux-2.6.18.8/drivers/acpi/processor_perflib.c linux-2.6.18-xen-3.3.0/drivers/acpi/processor_perflib.c
+--- linux-2.6.18.8/drivers/acpi/processor_perflib.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/processor_perflib.c 2008-08-21 11:36:07.000000000 +0200
+@@ -66,6 +66,7 @@ static DEFINE_MUTEX(performance_mutex);
+
+ static int acpi_processor_ppc_status = 0;
+
++#ifdef CONFIG_CPU_FREQ
+ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+ {
+@@ -102,6 +103,7 @@ static int acpi_processor_ppc_notifier(s
+ static struct notifier_block acpi_ppc_notifier_block = {
+ .notifier_call = acpi_processor_ppc_notifier,
+ };
++#endif /* CONFIG_CPU_FREQ */
+
+ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
+ {
+@@ -137,9 +139,15 @@ int acpi_processor_ppc_has_changed(struc
+ if (ret < 0)
+ return (ret);
+ else
++#ifdef CONFIG_CPU_FREQ
+ return cpufreq_update_policy(pr->id);
++#elif CONFIG_PROCESSOR_EXTERNAL_CONTROL
++ return processor_notify_external(pr,
++ PROCESSOR_PM_CHANGE, PM_TYPE_PERF);
++#endif
+ }
+
++#ifdef CONFIG_CPU_FREQ
+ void acpi_processor_ppc_init(void)
+ {
+ if (!cpufreq_register_notifier
+@@ -158,6 +166,7 @@ void acpi_processor_ppc_exit(void)
+
+ acpi_processor_ppc_status &= ~PPC_REGISTERED;
+ }
++#endif /* CONFIG_CPU_FREQ */
+
+ static int acpi_processor_get_performance_control(struct acpi_processor *pr)
+ {
+@@ -299,7 +308,10 @@ static int acpi_processor_get_performanc
+ return result;
+ }
+
+-static int acpi_processor_get_performance_info(struct acpi_processor *pr)
++#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++static
++#endif
++int acpi_processor_get_performance_info(struct acpi_processor *pr)
+ {
+ int result = 0;
+ acpi_status status = AE_OK;
+@@ -331,6 +343,7 @@ static int acpi_processor_get_performanc
+ return 0;
+ }
+
++#ifdef CONFIG_CPU_FREQ
+ int acpi_processor_notify_smm(struct module *calling_module)
+ {
+ acpi_status status;
+@@ -398,6 +411,7 @@ int acpi_processor_notify_smm(struct mod
+ }
+
+ EXPORT_SYMBOL(acpi_processor_notify_smm);
++#endif /* CONFIG_CPU_FREQ */
+
+ #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
+ /* /proc/acpi/processor/../performance interface (DEPRECATED) */
+@@ -538,7 +552,10 @@ static void acpi_cpufreq_remove_file(str
+ }
+ #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
+
+-static int acpi_processor_get_psd(struct acpi_processor *pr)
++#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++static
+#endif
++int acpi_processor_get_psd(struct acpi_processor *pr)
+ {
+ int result = 0;
+ acpi_status status = AE_OK;
+diff -rpuN linux-2.6.18.8/drivers/acpi/resources/rsxface.c linux-2.6.18-xen-3.3.0/drivers/acpi/resources/rsxface.c
+--- linux-2.6.18.8/drivers/acpi/resources/rsxface.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/resources/rsxface.c 2008-08-21 11:36:07.000000000 +0200
+@@ -476,8 +476,6 @@ acpi_rs_match_vendor_resource(struct acp
+ return (AE_CTRL_TERMINATE);
}
- ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
-diff -rpuN linux-2.6.18.8/drivers/acpi/sleep/main.c linux-2.6.18-xen-3.2.0/drivers/acpi/sleep/main.c
---- linux-2.6.18.8/drivers/acpi/sleep/main.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/acpi/sleep/main.c 2008-02-15 16:21:57.000000000 -0800
+-ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource)
+-
+ /*******************************************************************************
+ *
+ * FUNCTION: acpi_walk_resources
+diff -rpuN linux-2.6.18.8/drivers/acpi/sleep/main.c linux-2.6.18-xen-3.3.0/drivers/acpi/sleep/main.c
+--- linux-2.6.18.8/drivers/acpi/sleep/main.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/sleep/main.c 2008-08-21 11:36:07.000000000 +0200
@@ -91,7 +91,14 @@ static int acpi_pm_enter(suspend_state_t
break;
@@ -73130,9 +74281,9 @@ diff -rpuN linux-2.6.18.8/drivers/acpi/sleep/main.c linux-2.6.18-xen-3.2.0/drive
return 0;
}
-diff -rpuN linux-2.6.18.8/drivers/acpi/sleep/poweroff.c linux-2.6.18-xen-3.2.0/drivers/acpi/sleep/poweroff.c
---- linux-2.6.18.8/drivers/acpi/sleep/poweroff.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/acpi/sleep/poweroff.c 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/acpi/sleep/poweroff.c linux-2.6.18-xen-3.3.0/drivers/acpi/sleep/poweroff.c
+--- linux-2.6.18.8/drivers/acpi/sleep/poweroff.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/sleep/poweroff.c 2008-08-21 11:36:07.000000000 +0200
@@ -20,6 +20,7 @@
int acpi_sleep_prepare(u32 acpi_state)
{
@@ -73149,9 +74300,21 @@ diff -rpuN linux-2.6.18.8/drivers/acpi/sleep/poweroff.c linux-2.6.18-xen-3.2.0/d
ACPI_FLUSH_CPU_CACHE();
acpi_enable_wakeup_device_prep(acpi_state);
#endif
-diff -rpuN linux-2.6.18.8/drivers/block/floppy.c linux-2.6.18-xen-3.2.0/drivers/block/floppy.c
---- linux-2.6.18.8/drivers/block/floppy.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/block/floppy.c 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/acpi/sleep/proc.c linux-2.6.18-xen-3.3.0/drivers/acpi/sleep/proc.c
+--- linux-2.6.18.8/drivers/acpi/sleep/proc.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/acpi/sleep/proc.c 2008-08-21 11:36:07.000000000 +0200
+@@ -251,6 +251,8 @@ acpi_system_write_alarm(struct file *fil
+
+ if (adjust) {
+ yr += CMOS_READ(RTC_YEAR);
++ if (acpi_gbl_FADT->century)
++ yr += CMOS_READ(acpi_gbl_FADT->century) * 100;
+ mo += CMOS_READ(RTC_MONTH);
+ day += CMOS_READ(RTC_DAY_OF_MONTH);
+ hr += CMOS_READ(RTC_HOURS);
+diff -rpuN linux-2.6.18.8/drivers/block/floppy.c linux-2.6.18-xen-3.3.0/drivers/block/floppy.c
+--- linux-2.6.18.8/drivers/block/floppy.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/block/floppy.c 2008-08-21 11:36:07.000000000 +0200
@@ -4392,11 +4392,15 @@ static int floppy_grab_irq_and_dma(void)
if (fd_request_dma()) {
DPRINT("Unable to grab DMA%d for the floppy driver\n",
@@ -73173,9 +74336,9 @@ diff -rpuN linux-2.6.18.8/drivers/block/floppy.c linux-2.6.18-xen-3.2.0/drivers/
}
for (fdc = 0; fdc < N_FDC; fdc++) {
-diff -rpuN linux-2.6.18.8/drivers/char/agp/amd64-agp.c linux-2.6.18-xen-3.2.0/drivers/char/agp/amd64-agp.c
---- linux-2.6.18.8/drivers/char/agp/amd64-agp.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/agp/amd64-agp.c 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/agp/amd64-agp.c linux-2.6.18-xen-3.3.0/drivers/char/agp/amd64-agp.c
+--- linux-2.6.18.8/drivers/char/agp/amd64-agp.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/agp/amd64-agp.c 2008-08-21 11:36:07.000000000 +0200
@@ -15,6 +15,7 @@
#include <linux/mmzone.h>
#include <asm/page.h> /* PAGE_SIZE */
@@ -73210,9 +74373,9 @@ diff -rpuN linux-2.6.18.8/drivers/char/agp/amd64-agp.c linux-2.6.18-xen-3.2.0/dr
}
/* Request the Aperture. This catches cases when someone else
-diff -rpuN linux-2.6.18.8/drivers/char/agp/generic.c linux-2.6.18-xen-3.2.0/drivers/char/agp/generic.c
---- linux-2.6.18.8/drivers/char/agp/generic.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/agp/generic.c 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/agp/generic.c linux-2.6.18-xen-3.3.0/drivers/char/agp/generic.c
+--- linux-2.6.18.8/drivers/char/agp/generic.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/agp/generic.c 2008-08-21 11:36:07.000000000 +0200
@@ -51,28 +51,6 @@ int agp_memory_reserved;
*/
EXPORT_SYMBOL_GPL(agp_memory_reserved);
@@ -73242,9 +74405,9 @@ diff -rpuN linux-2.6.18.8/drivers/char/agp/generic.c linux-2.6.18-xen-3.2.0/driv
/*
* Generic routines for handling agp_memory structures -
* They use the basic page allocation routines to do the brunt of the work.
-diff -rpuN linux-2.6.18.8/drivers/char/agp/intel-agp.c linux-2.6.18-xen-3.2.0/drivers/char/agp/intel-agp.c
---- linux-2.6.18.8/drivers/char/agp/intel-agp.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/agp/intel-agp.c 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/agp/intel-agp.c linux-2.6.18-xen-3.3.0/drivers/char/agp/intel-agp.c
+--- linux-2.6.18.8/drivers/char/agp/intel-agp.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/agp/intel-agp.c 2008-08-21 11:36:07.000000000 +0200
@@ -164,9 +164,17 @@ static void *i8xx_alloc_pages(void)
if (page == NULL)
return NULL;
@@ -73278,9 +74441,21 @@ diff -rpuN linux-2.6.18.8/drivers/char/agp/intel-agp.c linux-2.6.18-xen-3.2.0/dr
atomic_dec(&agp_bridge->current_memory_agp);
}
-diff -rpuN linux-2.6.18.8/drivers/char/mem.c linux-2.6.18-xen-3.2.0/drivers/char/mem.c
---- linux-2.6.18.8/drivers/char/mem.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/mem.c 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/Kconfig linux-2.6.18-xen-3.3.0/drivers/char/Kconfig
+--- linux-2.6.18.8/drivers/char/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -1005,7 +1005,7 @@ config MAX_RAW_DEVS
+ config HPET
+ bool "HPET - High Precision Event Timer" if (X86 || IA64)
+ default n
+- depends on ACPI
++ depends on ACPI && !XEN
+ help
+ If you say Y here, you will have a miscdevice named "/dev/hpet/". Each
+ open selects one of the timers supported by the HPET. The timers are
+diff -rpuN linux-2.6.18.8/drivers/char/mem.c linux-2.6.18-xen-3.3.0/drivers/char/mem.c
+--- linux-2.6.18.8/drivers/char/mem.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/mem.c 2008-08-21 11:36:07.000000000 +0200
@@ -101,6 +101,7 @@ static inline int valid_mmap_phys_addr_r
}
#endif
@@ -73297,7 +74472,31 @@ diff -rpuN linux-2.6.18.8/drivers/char/mem.c linux-2.6.18-xen-3.2.0/drivers/char
#ifndef __HAVE_PHYS_MEM_ACCESS_PROT
static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
-@@ -780,6 +782,7 @@ static int open_port(struct inode * inod
+@@ -262,6 +264,9 @@ static int mmap_mem(struct file * file,
+ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
+ {
+ unsigned long pfn;
++#ifdef CONFIG_XEN
++ unsigned long i, count;
++#endif
+
+ /* Turn a kernel-virtual address into a physical page frame */
+ pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
+@@ -276,6 +281,13 @@ static int mmap_kmem(struct file * file,
+ if (!pfn_valid(pfn))
+ return -EIO;
+
++#ifdef CONFIG_XEN
++ count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
++ for (i = 0; i < count; i++)
++ if ((pfn + i) != mfn_to_local_pfn(pfn_to_mfn(pfn + i)))
++ return -EIO;
++#endif
++
+ vma->vm_pgoff = pfn;
+ return mmap_mem(file, vma);
+ }
+@@ -780,6 +792,7 @@ static int open_port(struct inode * inod
#define open_kmem open_mem
#define open_oldmem open_mem
@@ -73305,7 +74504,7 @@ diff -rpuN linux-2.6.18.8/drivers/char/mem.c linux-2.6.18-xen-3.2.0/drivers/char
static const struct file_operations mem_fops = {
.llseek = memory_lseek,
.read = read_mem,
-@@ -787,6 +790,9 @@ static const struct file_operations mem_
+@@ -787,6 +800,9 @@ static const struct file_operations mem_
.mmap = mmap_mem,
.open = open_mem,
};
@@ -73315,9 +74514,9 @@ diff -rpuN linux-2.6.18.8/drivers/char/mem.c linux-2.6.18-xen-3.2.0/drivers/char
static const struct file_operations kmem_fops = {
.llseek = memory_lseek,
-diff -rpuN linux-2.6.18.8/drivers/char/tpm/Kconfig linux-2.6.18-xen-3.2.0/drivers/char/tpm/Kconfig
---- linux-2.6.18.8/drivers/char/tpm/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/tpm/Kconfig 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/tpm/Kconfig linux-2.6.18-xen-3.3.0/drivers/char/tpm/Kconfig
+--- linux-2.6.18.8/drivers/char/tpm/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/tpm/Kconfig 2008-08-21 11:36:07.000000000 +0200
@@ -58,5 +58,13 @@ config TCG_INFINEON
Further information on this driver and the supported hardware
can be found at http://www.prosec.rub.de/tpm
@@ -73333,18 +74532,18 @@ diff -rpuN linux-2.6.18.8/drivers/char/tpm/Kconfig linux-2.6.18-xen-3.2.0/driver
+ will be called tpm_xenu.
+endmenu
-diff -rpuN linux-2.6.18.8/drivers/char/tpm/Makefile linux-2.6.18-xen-3.2.0/drivers/char/tpm/Makefile
---- linux-2.6.18.8/drivers/char/tpm/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/tpm/Makefile 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/tpm/Makefile linux-2.6.18-xen-3.3.0/drivers/char/tpm/Makefile
+--- linux-2.6.18.8/drivers/char/tpm/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/tpm/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -9,3 +9,5 @@ obj-$(CONFIG_TCG_TIS) += tpm_tis.o
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+obj-$(CONFIG_TCG_XEN) += tpm_xenu.o
+tpm_xenu-y = tpm_xen.o tpm_vtpm.o
-diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm.h linux-2.6.18-xen-3.2.0/drivers/char/tpm/tpm.h
---- linux-2.6.18.8/drivers/char/tpm/tpm.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/tpm/tpm.h 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm.h linux-2.6.18-xen-3.3.0/drivers/char/tpm/tpm.h
+--- linux-2.6.18.8/drivers/char/tpm/tpm.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/tpm/tpm.h 2008-08-21 11:36:07.000000000 +0200
@@ -105,6 +105,9 @@ struct tpm_chip {
struct dentry **bios_dir;
@@ -73374,9 +74573,9 @@ diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm.h linux-2.6.18-xen-3.2.0/drivers/
extern void tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
extern void tpm_continue_selftest(struct tpm_chip *);
-diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.c linux-2.6.18-xen-3.2.0/drivers/char/tpm/tpm_vtpm.c
---- linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/tpm/tpm_vtpm.c 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.c linux-2.6.18-xen-3.3.0/drivers/char/tpm/tpm_vtpm.c
+--- linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/tpm/tpm_vtpm.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2006 IBM Corporation
@@ -73920,9 +75119,9 @@ diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.c linux-2.6.18-xen-3.2.0/dri
+ tpm_remove_hardware(dev);
+ kfree(vtpms);
+}
-diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.h linux-2.6.18-xen-3.2.0/drivers/char/tpm/tpm_vtpm.h
---- linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/tpm/tpm_vtpm.h 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.h linux-2.6.18-xen-3.3.0/drivers/char/tpm/tpm_vtpm.h
+--- linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/tpm/tpm_vtpm.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,55 @@
+#ifndef TPM_VTPM_H
+#define TPM_VTPM_H
@@ -73979,10 +75178,10 @@ diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_vtpm.h linux-2.6.18-xen-3.2.0/dri
+}
+
+#endif
-diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_xen.c linux-2.6.18-xen-3.2.0/drivers/char/tpm/tpm_xen.c
---- linux-2.6.18.8/drivers/char/tpm/tpm_xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/tpm/tpm_xen.c 2008-02-15 16:21:57.000000000 -0800
-@@ -0,0 +1,720 @@
+diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_xen.c linux-2.6.18-xen-3.3.0/drivers/char/tpm/tpm_xen.c
+--- linux-2.6.18.8/drivers/char/tpm/tpm_xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/tpm/tpm_xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,722 @@
+/*
+ * Copyright (c) 2005, IBM Corporation
+ *
@@ -74332,6 +75531,8 @@ diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_xen.c linux-2.6.18-xen-3.2.0/driv
+ case XenbusStateInitialising:
+ case XenbusStateInitWait:
+ case XenbusStateInitialised:
++ case XenbusStateReconfiguring:
++ case XenbusStateReconfigured:
+ case XenbusStateUnknown:
+ break;
+
@@ -74703,9 +75904,9 @@ diff -rpuN linux-2.6.18.8/drivers/char/tpm/tpm_xen.c linux-2.6.18-xen-3.2.0/driv
+module_init(tpmif_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/char/tty_io.c linux-2.6.18-xen-3.2.0/drivers/char/tty_io.c
---- linux-2.6.18.8/drivers/char/tty_io.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/char/tty_io.c 2008-02-15 16:21:57.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/char/tty_io.c linux-2.6.18-xen-3.3.0/drivers/char/tty_io.c
+--- linux-2.6.18.8/drivers/char/tty_io.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/char/tty_io.c 2008-08-21 11:36:07.000000000 +0200
@@ -130,6 +130,8 @@ LIST_HEAD(tty_drivers); /* linked list
vt.c for deeply disgusting hack reasons */
DEFINE_MUTEX(tty_mutex);
@@ -74741,9 +75942,9 @@ diff -rpuN linux-2.6.18.8/drivers/char/tty_io.c linux-2.6.18-xen-3.2.0/drivers/c
#endif
return 0;
}
-diff -rpuN linux-2.6.18.8/drivers/cpufreq/cpufreq_ondemand.c linux-2.6.18-xen-3.2.0/drivers/cpufreq/cpufreq_ondemand.c
---- linux-2.6.18.8/drivers/cpufreq/cpufreq_ondemand.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/cpufreq/cpufreq_ondemand.c 2008-02-15 16:21:58.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/cpufreq/cpufreq_ondemand.c linux-2.6.18-xen-3.3.0/drivers/cpufreq/cpufreq_ondemand.c
+--- linux-2.6.18.8/drivers/cpufreq/cpufreq_ondemand.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/cpufreq/cpufreq_ondemand.c 2008-08-21 11:36:07.000000000 +0200
@@ -96,6 +96,7 @@ static inline cputime64_t get_cpu_idle_t
return retval;
}
@@ -74866,9 +76067,9 @@ diff -rpuN linux-2.6.18.8/drivers/cpufreq/cpufreq_ondemand.c linux-2.6.18-xen-3.
/* Check for frequency increase */
if (load > dbs_tuners_ins.up_threshold) {
-diff -rpuN linux-2.6.18.8/drivers/cpufreq/cpufreq_stats.c linux-2.6.18-xen-3.2.0/drivers/cpufreq/cpufreq_stats.c
---- linux-2.6.18.8/drivers/cpufreq/cpufreq_stats.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/cpufreq/cpufreq_stats.c 2008-02-15 16:21:58.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/cpufreq/cpufreq_stats.c linux-2.6.18-xen-3.3.0/drivers/cpufreq/cpufreq_stats.c
+--- linux-2.6.18.8/drivers/cpufreq/cpufreq_stats.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/cpufreq/cpufreq_stats.c 2008-08-21 11:36:07.000000000 +0200
@@ -292,6 +292,9 @@ cpufreq_stat_notifier_trans (struct noti
if (old_index == new_index)
return 0;
@@ -74879,39 +76080,54 @@ diff -rpuN linux-2.6.18.8/drivers/cpufreq/cpufreq_stats.c linux-2.6.18-xen-3.2.0
spin_lock(&cpufreq_stats_lock);
stat->last_index = new_index;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
-diff -rpuN linux-2.6.18.8/drivers/i2c/busses/Kconfig linux-2.6.18-xen-3.2.0/drivers/i2c/busses/Kconfig
---- linux-2.6.18.8/drivers/i2c/busses/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/i2c/busses/Kconfig 2008-02-15 16:21:58.000000000 -0800
-@@ -125,6 +125,7 @@ config I2C_I801
- ICH7
- ESB2
- ICH8
-+ ICH9
-
- This driver can also be built as a module. If so, the module
- will be called i2c-i801.
-diff -rpuN linux-2.6.18.8/drivers/i2c/busses/i2c-i801.c linux-2.6.18-xen-3.2.0/drivers/i2c/busses/i2c-i801.c
---- linux-2.6.18.8/drivers/i2c/busses/i2c-i801.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/i2c/busses/i2c-i801.c 2008-02-15 16:21:58.000000000 -0800
-@@ -33,6 +33,7 @@
+diff -rpuN linux-2.6.18.8/drivers/cpufreq/Kconfig linux-2.6.18-xen-3.3.0/drivers/cpufreq/Kconfig
+--- linux-2.6.18.8/drivers/cpufreq/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/cpufreq/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -1,5 +1,6 @@
+ config CPU_FREQ
+ bool "CPU Frequency scaling"
++ depends on !PROCESSOR_EXTERNAL_CONTROL
+ help
+ CPU Frequency scaling allows you to change the clock speed of
+ CPUs on the fly. This is a nice method to save power, because
+diff -rpuN linux-2.6.18.8/drivers/i2c/busses/i2c-i801.c linux-2.6.18-xen-3.3.0/drivers/i2c/busses/i2c-i801.c
+--- linux-2.6.18.8/drivers/i2c/busses/i2c-i801.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/i2c/busses/i2c-i801.c 2008-08-21 11:36:07.000000000 +0200
+@@ -33,6 +33,9 @@
ICH7 27DA
ESB2 269B
ICH8 283E
+ ICH9 2930
++ ICH10 3A30
++ ICH10 3A60
This driver supports several versions of Intel's I/O Controller Hubs (ICH).
For SMBus support, they are similar to the PIIX4 and are part
of Intel's '810' and other chipsets.
-@@ -457,6 +458,7 @@ static struct pci_device_id i801_ids[] =
+@@ -457,6 +460,9 @@ static struct pci_device_id i801_ids[] =
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
{ 0, }
};
-diff -rpuN linux-2.6.18.8/drivers/ide/ide-lib.c linux-2.6.18-xen-3.2.0/drivers/ide/ide-lib.c
---- linux-2.6.18.8/drivers/ide/ide-lib.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/ide/ide-lib.c 2008-02-15 16:21:58.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/i2c/busses/Kconfig linux-2.6.18-xen-3.3.0/drivers/i2c/busses/Kconfig
+--- linux-2.6.18.8/drivers/i2c/busses/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/i2c/busses/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -125,6 +125,8 @@ config I2C_I801
+ ICH7
+ ESB2
+ ICH8
++ ICH9
++ ICH10
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-i801.
+diff -rpuN linux-2.6.18.8/drivers/ide/ide-lib.c linux-2.6.18-xen-3.3.0/drivers/ide/ide-lib.c
+--- linux-2.6.18.8/drivers/ide/ide-lib.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/ide/ide-lib.c 2008-08-21 11:36:07.000000000 +0200
@@ -408,10 +408,10 @@ void ide_toggle_bounce(ide_drive_t *driv
{
u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */
@@ -74927,9 +76143,64 @@ diff -rpuN linux-2.6.18.8/drivers/ide/ide-lib.c linux-2.6.18-xen-3.2.0/drivers/i
addr = HWIF(drive)->pci_dev->dma_mask;
}
-diff -rpuN linux-2.6.18.8/drivers/net/r8169.c linux-2.6.18-xen-3.2.0/drivers/net/r8169.c
---- linux-2.6.18.8/drivers/net/r8169.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/net/r8169.c 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/ide/pci/atiixp.c linux-2.6.18-xen-3.3.0/drivers/ide/pci/atiixp.c
+--- linux-2.6.18.8/drivers/ide/pci/atiixp.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/ide/pci/atiixp.c 2008-08-21 11:36:07.000000000 +0200
+@@ -348,6 +348,7 @@ static struct pci_device_id atiixp_pci_t
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
++ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { 0, },
+ };
+ MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
+diff -rpuN linux-2.6.18.8/drivers/input/gameport/gameport.c linux-2.6.18-xen-3.3.0/drivers/input/gameport/gameport.c
+--- linux-2.6.18.8/drivers/input/gameport/gameport.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/input/gameport/gameport.c 2008-08-21 11:36:07.000000000 +0200
+@@ -37,8 +37,6 @@ EXPORT_SYMBOL(gameport_unregister_driver
+ EXPORT_SYMBOL(gameport_open);
+ EXPORT_SYMBOL(gameport_close);
+ EXPORT_SYMBOL(gameport_rescan);
+-EXPORT_SYMBOL(gameport_cooked_read);
+-EXPORT_SYMBOL(gameport_set_name);
+ EXPORT_SYMBOL(gameport_set_phys);
+ EXPORT_SYMBOL(gameport_start_polling);
+ EXPORT_SYMBOL(gameport_stop_polling);
+diff -rpuN linux-2.6.18.8/drivers/Makefile linux-2.6.18-xen-3.3.0/drivers/Makefile
+--- linux-2.6.18.8/drivers/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -31,6 +31,7 @@ obj-y += base/ block/ misc/ mfd/ net/
+ obj-$(CONFIG_NUBUS) += nubus/
+ obj-$(CONFIG_ATM) += atm/
+ obj-$(CONFIG_PPC_PMAC) += macintosh/
++obj-$(CONFIG_XEN) += xen/
+ obj-$(CONFIG_IDE) += ide/
+ obj-$(CONFIG_FC4) += fc4/
+ obj-$(CONFIG_SCSI) += scsi/
+diff -rpuN linux-2.6.18.8/drivers/net/Kconfig linux-2.6.18-xen-3.3.0/drivers/net/Kconfig
+--- linux-2.6.18.8/drivers/net/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -2399,6 +2399,8 @@ config MYRI10GE
+ <file:Documentation/networking/net-modules.txt>. The module
+ will be called myri10ge.
+
++source "drivers/net/sfc/Kconfig"
++
+ endmenu
+
+ source "drivers/net/tokenring/Kconfig"
+diff -rpuN linux-2.6.18.8/drivers/net/Makefile linux-2.6.18-xen-3.3.0/drivers/net/Makefile
+--- linux-2.6.18.8/drivers/net/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -219,3 +219,5 @@ obj-$(CONFIG_NETCONSOLE) += netconsole.o
+
+ obj-$(CONFIG_FS_ENET) += fs_enet/
+
++obj-$(CONFIG_SFC) += sfc/
++
+diff -rpuN linux-2.6.18.8/drivers/net/r8169.c linux-2.6.18-xen-3.3.0/drivers/net/r8169.c
+--- linux-2.6.18.8/drivers/net/r8169.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/r8169.c 2008-08-21 11:36:07.000000000 +0200
@@ -6,26 +6,26 @@
History:
Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>.
@@ -76241,9 +77512,42687 @@ diff -rpuN linux-2.6.18.8/drivers/net/r8169.c linux-2.6.18-xen-3.2.0/drivers/net
}
static void __exit
-diff -rpuN linux-2.6.18.8/drivers/oprofile/buffer_sync.c linux-2.6.18-xen-3.2.0/drivers/oprofile/buffer_sync.c
---- linux-2.6.18.8/drivers/oprofile/buffer_sync.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/oprofile/buffer_sync.c 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/alaska.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/alaska.c
+--- linux-2.6.18.8/drivers/net/sfc/alaska.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/alaska.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,159 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005: Fen Systems Ltd.
++ * Copyright 2006-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "net_driver.h"
++#include <linux/ethtool.h>
++#include "gmii.h"
++#include "phy.h"
++
++/* Marvell 88E1111 "Alaska" PHY control */
++#define ALASKA_PHY_SPECIFIC 16
++#define ALASKA_ALLOW_SLEEP 0x0200
++
++#define ALASKA_EXTENDED_CONTROL 20
++#define EXTENDED_LINE_LOOPBACK 0x8000
++
++#define ALASKA_LED_CONTROL 24
++#define LED_BLINK_MASK 0x0700
++#define LED_BLINK_FAST 0x0100
++#define LED_BLINK_SLOW 0x0300
++#define LED_TX_CTRL_MASK 0x0041
++#define LED_TX_CTRL_LINK_AND_ACTIVITY 0x0001
++
++#define ALASKA_LED_OVERRIDE 25
++#define LED_LINK1000_MASK 0x0030
++#define LED_LINK1000_BLINK 0x0010
++#define LED_TX_MASK 0x0003
++#define LED_TX_BLINK 0x0001
++
++static void alaska_reconfigure(struct efx_nic *efx)
++{
++ struct mii_if_info *gmii = &efx->mii;
++ u32 bmcr, phy_ext;
++
++ /* Configure line loopback if requested */
++ phy_ext = gmii->mdio_read(gmii->dev, gmii->phy_id,
++ ALASKA_EXTENDED_CONTROL);
++ if (efx->loopback_mode == LOOPBACK_NETWORK)
++ phy_ext |= EXTENDED_LINE_LOOPBACK;
++ else
++ phy_ext &= ~EXTENDED_LINE_LOOPBACK;
++ gmii->mdio_write(gmii->dev, gmii->phy_id, ALASKA_EXTENDED_CONTROL,
++ phy_ext);
++
++ /* Configure PHY loopback if requested */
++ bmcr = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_BMCR);
++ if (efx->loopback_mode == LOOPBACK_PHY)
++ bmcr |= BMCR_LOOPBACK;
++ else
++ bmcr &= ~BMCR_LOOPBACK;
++ gmii->mdio_write(gmii->dev, gmii->phy_id, MII_BMCR, bmcr);
++
++ /* Read link up status */
++ if (efx->loopback_mode == LOOPBACK_NONE)
++ efx->link_up = mii_link_ok(gmii);
++ else
++ efx->link_up = 1;
++
++ /* Determine link options from PHY */
++ if (gmii->force_media) {
++ efx->link_options = gmii_forced_result(bmcr);
++ } else {
++ int lpa = gmii_lpa(gmii);
++ int adv = gmii_advertised(gmii);
++ efx->link_options = gmii_nway_result(adv & lpa);
++ }
++}
++
++static void alaska_clear_interrupt(struct efx_nic *efx)
++{
++ struct mii_if_info *gmii = &efx->mii;
++
++ /* Read interrupt status register to clear */
++ gmii->mdio_read(gmii->dev, gmii->phy_id, GMII_ISR);
++}
++
++static int alaska_init(struct efx_nic *efx)
++{
++ struct mii_if_info *gmii = &efx->mii;
++ u32 ier, leds, ctrl_1g, phy_spec;
++
++ /* Read ISR to clear any outstanding PHY interrupts */
++ gmii->mdio_read(gmii->dev, gmii->phy_id, GMII_ISR);
++
++ /* Enable PHY interrupts */
++ ier = gmii->mdio_read(gmii->dev, gmii->phy_id, GMII_IER);
++ ier |= IER_LINK_CHG;
++ gmii->mdio_write(gmii->dev, gmii->phy_id, GMII_IER, ier);
++
++ /* Remove 1G half-duplex as unsupported in Mentor MAC */
++ ctrl_1g = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_CTRL1000);
++ ctrl_1g &= ~(ADVERTISE_1000HALF);
++ gmii->mdio_write(gmii->dev, gmii->phy_id, MII_CTRL1000, ctrl_1g);
++
++ /*
++ * The PHY can save power when there is no external connection
++ * (sleep mode). However, this is incompatible with PHY
++ * loopback, and if enable and disable it quickly the PHY can
++ * go to sleep even when sleep mode is disabled. (SFC bug
++ * 9309.) Therefore we disable it all the time.
++ */
++ phy_spec = gmii->mdio_read(gmii->dev, gmii->phy_id,
++ ALASKA_PHY_SPECIFIC);
++ phy_spec &= ~ALASKA_ALLOW_SLEEP;
++ gmii->mdio_write(gmii->dev, gmii->phy_id, ALASKA_PHY_SPECIFIC,
++ phy_spec);
++
++ /* Configure LEDs */
++ leds = gmii->mdio_read(gmii->dev, gmii->phy_id, ALASKA_LED_CONTROL);
++ leds &= ~(LED_BLINK_MASK | LED_TX_CTRL_MASK);
++ leds |= (LED_BLINK_FAST | LED_TX_CTRL_LINK_AND_ACTIVITY);
++ gmii->mdio_write(gmii->dev, gmii->phy_id, ALASKA_LED_CONTROL, leds);
++
++ return 0;
++}
++
++static void alaska_fini(struct efx_nic *efx)
++{
++ struct mii_if_info *gmii = &efx->mii;
++ u32 ier;
++
++ /* Disable PHY interrupts */
++ ier = gmii->mdio_read(gmii->dev, gmii->phy_id, GMII_IER);
++ ier &= ~IER_LINK_CHG;
++ gmii->mdio_write(gmii->dev, gmii->phy_id, GMII_IER, ier);
++}
++
++
++struct efx_phy_operations alaska_phy_operations = {
++ .init = alaska_init,
++ .fini = alaska_fini,
++ .reconfigure = alaska_reconfigure,
++ .clear_interrupt = alaska_clear_interrupt,
++ .loopbacks = (1 << LOOPBACK_PHY) | (1 << LOOPBACK_NETWORK),
++ .startup_loopback = LOOPBACK_PHY,
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/bitfield.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/bitfield.h
+--- linux-2.6.18.8/drivers/net/sfc/bitfield.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/bitfield.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,544 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_BITFIELD_H
++#define EFX_BITFIELD_H
++
++/*
++ * Efx bitfield access
++ *
++ * Efx NICs make extensive use of bitfields up to 128 bits
++ * wide. Since there is no native 128-bit datatype on most systems,
++ * and since 64-bit datatypes are inefficient on 32-bit systems and
++ * vice versa, we wrap accesses in a way that uses the most efficient
++ * datatype.
++ *
++ * The NICs are PCI devices and therefore little-endian. Since most
++ * of the quantities that we deal with are DMAed to/from host memory,
++ * we define our datatypes (efx_oword_t, efx_qword_t and
++ * efx_dword_t) to be little-endian.
++ */
++
++/* Lowest bit numbers and widths */
++#define EFX_DUMMY_FIELD_LBN 0
++#define EFX_DUMMY_FIELD_WIDTH 0
++#define EFX_DWORD_0_LBN 0
++#define EFX_DWORD_0_WIDTH 32
++#define EFX_DWORD_1_LBN 32
++#define EFX_DWORD_1_WIDTH 32
++#define EFX_DWORD_2_LBN 64
++#define EFX_DWORD_2_WIDTH 32
++#define EFX_DWORD_3_LBN 96
++#define EFX_DWORD_3_WIDTH 32
++
++#define EFX_BYTE 1
++#define EFX_WORD 2
++#define EFX_DWORD 4
++#define EFX_OWORD 8
++
++/* Specified attribute (e.g. LBN) of the specified field */
++#define EFX_VAL(field, attribute) field ## _ ## attribute
++/* Low bit number of the specified field */
++#define EFX_LOW_BIT(field) EFX_VAL(field, LBN)
++/* Bit width of the specified field */
++#define EFX_WIDTH(field) EFX_VAL(field, WIDTH)
++/* High bit number of the specified field */
++#define EFX_HIGH_BIT(field) (EFX_LOW_BIT(field) + EFX_WIDTH(field) - 1)
++/* Mask equal in width to the specified field.
++ *
++ * For example, a field with width 5 would have a mask of 0x1f.
++ *
++ * The maximum width mask that can be generated is 64 bits.
++ */
++#define EFX_MASK64(field) \
++ (EFX_WIDTH(field) == 64 ? ~((u64) 0) : \
++ (((((u64) 1) << EFX_WIDTH(field))) - 1))
++
++/* Mask equal in width to the specified field.
++ *
++ * For example, a field with width 5 would have a mask of 0x1f.
++ *
++ * The maximum width mask that can be generated is 32 bits. Use
++ * EFX_MASK64 for higher width fields.
++ */
++#define EFX_MASK32(field) \
++ (EFX_WIDTH(field) == 32 ? ~((u32) 0) : \
++ (((((u32) 1) << EFX_WIDTH(field))) - 1))
++
++/* A doubleword (i.e. 4 byte) datatype - little-endian in HW */
++typedef union efx_dword {
++ __le32 u32[1];
++} efx_dword_t;
++
++/* A quadword (i.e. 8 byte) datatype - little-endian in HW */
++typedef union efx_qword {
++ __le64 u64[1];
++ __le32 u32[2];
++ efx_dword_t dword[2];
++} efx_qword_t;
++
++/* An octword (eight-word, i.e. 16 byte) datatype - little-endian in HW */
++typedef union efx_oword {
++ __le64 u64[2];
++ efx_qword_t qword[2];
++ __le32 u32[4];
++ efx_dword_t dword[4];
++} efx_oword_t;
++
++/* Format string and value expanders for printk */
++#define EFX_DWORD_FMT "%08x"
++#define EFX_QWORD_FMT "%08x:%08x"
++#define EFX_OWORD_FMT "%08x:%08x:%08x:%08x"
++#define EFX_DWORD_VAL(dword) \
++ ((unsigned int) le32_to_cpu((dword).u32[0]))
++#define EFX_QWORD_VAL(qword) \
++ ((unsigned int) le32_to_cpu((qword).u32[1])), \
++ ((unsigned int) le32_to_cpu((qword).u32[0]))
++#define EFX_OWORD_VAL(oword) \
++ ((unsigned int) le32_to_cpu((oword).u32[3])), \
++ ((unsigned int) le32_to_cpu((oword).u32[2])), \
++ ((unsigned int) le32_to_cpu((oword).u32[1])), \
++ ((unsigned int) le32_to_cpu((oword).u32[0]))
++
++/*
++ * Extract bit field portion [low,high) from the native-endian element
++ * which contains bits [min,max).
++ *
++ * For example, suppose "element" represents the high 32 bits of a
++ * 64-bit value, and we wish to extract the bits belonging to the bit
++ * field occupying bits 28-45 of this 64-bit value.
++ *
++ * Then EFX_EXTRACT ( element, 32, 63, 28, 45 ) would give
++ *
++ * ( element ) << 4
++ *
++ * The result will contain the relevant bits filled in in the range
++ * [0,high-low), with garbage in bits [high-low+1,...).
++ */
++#define EFX_EXTRACT_NATIVE(native_element, min, max, low, high) \
++ (((low > max) || (high < min)) ? 0 : \
++ ((low > min) ? \
++ ((native_element) >> (low - min)) : \
++ ((native_element) << (min - low))))
++
++/*
++ * Extract bit field portion [low,high) from the 64-bit little-endian
++ * element which contains bits [min,max)
++ */
++#define EFX_EXTRACT64(element, min, max, low, high) \
++ EFX_EXTRACT_NATIVE(le64_to_cpu(element), min, max, low, high)
++
++/*
++ * Extract bit field portion [low,high) from the 32-bit little-endian
++ * element which contains bits [min,max)
++ */
++#define EFX_EXTRACT32(element, min, max, low, high) \
++ EFX_EXTRACT_NATIVE(le32_to_cpu(element), min, max, low, high)
++
++#define EFX_EXTRACT_OWORD64(oword, low, high) \
++ (EFX_EXTRACT64((oword).u64[0], 0, 63, low, high) | \
++ EFX_EXTRACT64((oword).u64[1], 64, 127, low, high))
++
++#define EFX_EXTRACT_QWORD64(qword, low, high) \
++ EFX_EXTRACT64((qword).u64[0], 0, 63, low, high)
++
++#define EFX_EXTRACT_OWORD32(oword, low, high) \
++ (EFX_EXTRACT32((oword).u32[0], 0, 31, low, high) | \
++ EFX_EXTRACT32((oword).u32[1], 32, 63, low, high) | \
++ EFX_EXTRACT32((oword).u32[2], 64, 95, low, high) | \
++ EFX_EXTRACT32((oword).u32[3], 96, 127, low, high))
++
++#define EFX_EXTRACT_QWORD32(qword, low, high) \
++ (EFX_EXTRACT32((qword).u32[0], 0, 31, low, high) | \
++ EFX_EXTRACT32((qword).u32[1], 32, 63, low, high))
++
++#define EFX_EXTRACT_DWORD(dword, low, high) \
++ EFX_EXTRACT32((dword).u32[0], 0, 31, low, high)
++
++#define EFX_OWORD_FIELD64(oword, field) \
++ (EFX_EXTRACT_OWORD64(oword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK64(field))
++
++#define EFX_QWORD_FIELD64(qword, field) \
++ (EFX_EXTRACT_QWORD64(qword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK64(field))
++
++#define EFX_OWORD_FIELD32(oword, field) \
++ (EFX_EXTRACT_OWORD32(oword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK32(field))
++
++#define EFX_QWORD_FIELD32(qword, field) \
++ (EFX_EXTRACT_QWORD32(qword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK32(field))
++
++#define EFX_DWORD_FIELD(dword, field) \
++ (EFX_EXTRACT_DWORD(dword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
++ & EFX_MASK32(field))
++
++#define EFX_OWORD_IS_ZERO64(oword) \
++ (((oword).u64[0] | (oword).u64[1]) == (__force __le64) 0)
++
++#define EFX_QWORD_IS_ZERO64(qword) \
++ (((qword).u64[0]) == (__force __le64) 0)
++
++#define EFX_OWORD_IS_ZERO32(oword) \
++ (((oword).u32[0] | (oword).u32[1] | (oword).u32[2] | (oword).u32[3]) \
++ == (__force __le32) 0)
++
++#define EFX_QWORD_IS_ZERO32(qword) \
++ (((qword).u32[0] | (qword).u32[1]) == (__force __le32) 0)
++
++#define EFX_DWORD_IS_ZERO(dword) \
++ (((dword).u32[0]) == (__force __le32) 0)
++
++#define EFX_OWORD_IS_ALL_ONES64(oword) \
++ (((oword).u64[0] & (oword).u64[1]) == ~((__force __le64) 0))
++
++#define EFX_QWORD_IS_ALL_ONES64(qword) \
++ ((qword).u64[0] == ~((__force __le64) 0))
++
++#define EFX_OWORD_IS_ALL_ONES32(oword) \
++ (((oword).u32[0] & (oword).u32[1] & (oword).u32[2] & (oword).u32[3]) \
++ == ~((__force __le32) 0))
++
++#define EFX_QWORD_IS_ALL_ONES32(qword) \
++ (((qword).u32[0] & (qword).u32[1]) == ~((__force __le32) 0))
++
++#define EFX_DWORD_IS_ALL_ONES(dword) \
++ ((dword).u32[0] == ~((__force __le32) 0))
++
++#if BITS_PER_LONG == 64
++#define EFX_OWORD_FIELD EFX_OWORD_FIELD64
++#define EFX_QWORD_FIELD EFX_QWORD_FIELD64
++#define EFX_OWORD_IS_ZERO EFX_OWORD_IS_ZERO64
++#define EFX_QWORD_IS_ZERO EFX_QWORD_IS_ZERO64
++#define EFX_OWORD_IS_ALL_ONES EFX_OWORD_IS_ALL_ONES64
++#define EFX_QWORD_IS_ALL_ONES EFX_QWORD_IS_ALL_ONES64
++#else
++#define EFX_OWORD_FIELD EFX_OWORD_FIELD32
++#define EFX_QWORD_FIELD EFX_QWORD_FIELD32
++#define EFX_OWORD_IS_ZERO EFX_OWORD_IS_ZERO32
++#define EFX_QWORD_IS_ZERO EFX_QWORD_IS_ZERO32
++#define EFX_OWORD_IS_ALL_ONES EFX_OWORD_IS_ALL_ONES32
++#define EFX_QWORD_IS_ALL_ONES EFX_QWORD_IS_ALL_ONES32
++#endif
++
++/*
++ * Construct bit field portion
++ *
++ * Creates the portion of the bit field [low,high) that lies within
++ * the range [min,max).
++ */
++#define EFX_INSERT_NATIVE64(min, max, low, high, value) \
++ (((low > max) || (high < min)) ? 0 : \
++ ((low > min) ? \
++ (((u64) (value)) << (low - min)) : \
++ (((u64) (value)) >> (min - low))))
++
++#define EFX_INSERT_NATIVE32(min, max, low, high, value) \
++ (((low > max) || (high < min)) ? 0 : \
++ ((low > min) ? \
++ (((u32) (value)) << (low - min)) : \
++ (((u32) (value)) >> (min - low))))
++
++#define EFX_INSERT_NATIVE(min, max, low, high, value) \
++ ((((max - min) >= 32) || ((high - low) >= 32)) ? \
++ EFX_INSERT_NATIVE64(min, max, low, high, value) : \
++ EFX_INSERT_NATIVE32(min, max, low, high, value))
++
++/*
++ * Construct bit field portion
++ *
++ * Creates the portion of the named bit field that lies within the
++ * range [min,max).
++ */
++#define EFX_INSERT_FIELD_NATIVE(min, max, field, value) \
++ EFX_INSERT_NATIVE(min, max, EFX_LOW_BIT(field), \
++ EFX_HIGH_BIT(field), value)
++
++/*
++ * Construct bit field
++ *
++ * Creates the portion of the named bit fields that lie within the
++ * range [min,max).
++ */
++#define EFX_INSERT_FIELDS_NATIVE(min, max, \
++ field1, value1, \
++ field2, value2, \
++ field3, value3, \
++ field4, value4, \
++ field5, value5, \
++ field6, value6, \
++ field7, value7, \
++ field8, value8, \
++ field9, value9, \
++ field10, value10) \
++ (EFX_INSERT_FIELD_NATIVE((min), (max), field1, (value1)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field2, (value2)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field3, (value3)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field4, (value4)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field5, (value5)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field6, (value6)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field7, (value7)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field8, (value8)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field9, (value9)) | \
++ EFX_INSERT_FIELD_NATIVE((min), (max), field10, (value10)))
++
++#define EFX_INSERT_FIELDS64(...) \
++ cpu_to_le64(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__))
++
++#define EFX_INSERT_FIELDS32(...) \
++ cpu_to_le32(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__))
++
++#define EFX_POPULATE_OWORD64(oword, ...) do { \
++ (oword).u64[0] = EFX_INSERT_FIELDS64(0, 63, __VA_ARGS__); \
++ (oword).u64[1] = EFX_INSERT_FIELDS64(64, 127, __VA_ARGS__); \
++ } while (0)
++
++#define EFX_POPULATE_QWORD64(qword, ...) do { \
++ (qword).u64[0] = EFX_INSERT_FIELDS64(0, 63, __VA_ARGS__); \
++ } while (0)
++
++#define EFX_POPULATE_OWORD32(oword, ...) do { \
++ (oword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
++ (oword).u32[1] = EFX_INSERT_FIELDS32(32, 63, __VA_ARGS__); \
++ (oword).u32[2] = EFX_INSERT_FIELDS32(64, 95, __VA_ARGS__); \
++ (oword).u32[3] = EFX_INSERT_FIELDS32(96, 127, __VA_ARGS__); \
++ } while (0)
++
++#define EFX_POPULATE_QWORD32(qword, ...) do { \
++ (qword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
++ (qword).u32[1] = EFX_INSERT_FIELDS32(32, 63, __VA_ARGS__); \
++ } while (0)
++
++#define EFX_POPULATE_DWORD(dword, ...) do { \
++ (dword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
++ } while (0)
++
++#if BITS_PER_LONG == 64
++#define EFX_POPULATE_OWORD EFX_POPULATE_OWORD64
++#define EFX_POPULATE_QWORD EFX_POPULATE_QWORD64
++#else
++#define EFX_POPULATE_OWORD EFX_POPULATE_OWORD32
++#define EFX_POPULATE_QWORD EFX_POPULATE_QWORD32
++#endif
++
++/* Populate an octword field with various numbers of arguments */
++#define EFX_POPULATE_OWORD_10 EFX_POPULATE_OWORD
++#define EFX_POPULATE_OWORD_9(oword, ...) \
++ EFX_POPULATE_OWORD_10(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_8(oword, ...) \
++ EFX_POPULATE_OWORD_9(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_7(oword, ...) \
++ EFX_POPULATE_OWORD_8(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_6(oword, ...) \
++ EFX_POPULATE_OWORD_7(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_5(oword, ...) \
++ EFX_POPULATE_OWORD_6(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_4(oword, ...) \
++ EFX_POPULATE_OWORD_5(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_3(oword, ...) \
++ EFX_POPULATE_OWORD_4(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_2(oword, ...) \
++ EFX_POPULATE_OWORD_3(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_OWORD_1(oword, ...) \
++ EFX_POPULATE_OWORD_2(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_ZERO_OWORD(oword) \
++ EFX_POPULATE_OWORD_1(oword, EFX_DUMMY_FIELD, 0)
++#define EFX_SET_OWORD(oword) \
++ EFX_POPULATE_OWORD_4(oword, \
++ EFX_DWORD_0, 0xffffffff, \
++ EFX_DWORD_1, 0xffffffff, \
++ EFX_DWORD_2, 0xffffffff, \
++ EFX_DWORD_3, 0xffffffff)
++
++/* Populate a quadword field with various numbers of arguments */
++#define EFX_POPULATE_QWORD_10 EFX_POPULATE_QWORD
++#define EFX_POPULATE_QWORD_9(qword, ...) \
++ EFX_POPULATE_QWORD_10(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_8(qword, ...) \
++ EFX_POPULATE_QWORD_9(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_7(qword, ...) \
++ EFX_POPULATE_QWORD_8(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_6(qword, ...) \
++ EFX_POPULATE_QWORD_7(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_5(qword, ...) \
++ EFX_POPULATE_QWORD_6(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_4(qword, ...) \
++ EFX_POPULATE_QWORD_5(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_3(qword, ...) \
++ EFX_POPULATE_QWORD_4(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_2(qword, ...) \
++ EFX_POPULATE_QWORD_3(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_QWORD_1(qword, ...) \
++ EFX_POPULATE_QWORD_2(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_ZERO_QWORD(qword) \
++ EFX_POPULATE_QWORD_1(qword, EFX_DUMMY_FIELD, 0)
++#define EFX_SET_QWORD(qword) \
++ EFX_POPULATE_QWORD_2(qword, \
++ EFX_DWORD_0, 0xffffffff, \
++ EFX_DWORD_1, 0xffffffff)
++
++/* Populate a dword field with various numbers of arguments */
++#define EFX_POPULATE_DWORD_10 EFX_POPULATE_DWORD
++#define EFX_POPULATE_DWORD_9(dword, ...) \
++ EFX_POPULATE_DWORD_10(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_8(dword, ...) \
++ EFX_POPULATE_DWORD_9(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_7(dword, ...) \
++ EFX_POPULATE_DWORD_8(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_6(dword, ...) \
++ EFX_POPULATE_DWORD_7(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_5(dword, ...) \
++ EFX_POPULATE_DWORD_6(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_4(dword, ...) \
++ EFX_POPULATE_DWORD_5(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_3(dword, ...) \
++ EFX_POPULATE_DWORD_4(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_2(dword, ...) \
++ EFX_POPULATE_DWORD_3(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_POPULATE_DWORD_1(dword, ...) \
++ EFX_POPULATE_DWORD_2(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
++#define EFX_ZERO_DWORD(dword) \
++ EFX_POPULATE_DWORD_1(dword, EFX_DUMMY_FIELD, 0)
++#define EFX_SET_DWORD(dword) \
++ EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 0xffffffff)
++
++/*
++ * Modify a named field within an already-populated structure. Used
++ * for read-modify-write operations.
++ *
++ */
++
++#define EFX_INVERT_OWORD(oword) do { \
++ (oword).u64[0] = ~((oword).u64[0]); \
++ (oword).u64[1] = ~((oword).u64[1]); \
++ } while (0)
++
++#define EFX_INSERT_FIELD64(...) \
++ cpu_to_le64(EFX_INSERT_FIELD_NATIVE(__VA_ARGS__))
++
++#define EFX_INSERT_FIELD32(...) \
++ cpu_to_le32(EFX_INSERT_FIELD_NATIVE(__VA_ARGS__))
++
++#define EFX_INPLACE_MASK64(min, max, field) \
++ EFX_INSERT_FIELD64(min, max, field, EFX_MASK64(field))
++
++#define EFX_INPLACE_MASK32(min, max, field) \
++ EFX_INSERT_FIELD32(min, max, field, EFX_MASK32(field))
++
++#define EFX_SET_OWORD_FIELD64(oword, field, value) do { \
++ (oword).u64[0] = (((oword).u64[0] \
++ & ~EFX_INPLACE_MASK64(0, 63, field)) \
++ | EFX_INSERT_FIELD64(0, 63, field, value)); \
++ (oword).u64[1] = (((oword).u64[1] \
++ & ~EFX_INPLACE_MASK64(64, 127, field)) \
++ | EFX_INSERT_FIELD64(64, 127, field, value)); \
++ } while (0)
++
++#define EFX_SET_QWORD_FIELD64(qword, field, value) do { \
++ (qword).u64[0] = (((qword).u64[0] \
++ & ~EFX_INPLACE_MASK64(0, 63, field)) \
++ | EFX_INSERT_FIELD64(0, 63, field, value)); \
++ } while (0)
++
++#define EFX_SET_OWORD_FIELD32(oword, field, value) do { \
++ (oword).u32[0] = (((oword).u32[0] \
++ & ~EFX_INPLACE_MASK32(0, 31, field)) \
++ | EFX_INSERT_FIELD32(0, 31, field, value)); \
++ (oword).u32[1] = (((oword).u32[1] \
++ & ~EFX_INPLACE_MASK32(32, 63, field)) \
++ | EFX_INSERT_FIELD32(32, 63, field, value)); \
++ (oword).u32[2] = (((oword).u32[2] \
++ & ~EFX_INPLACE_MASK32(64, 95, field)) \
++ | EFX_INSERT_FIELD32(64, 95, field, value)); \
++ (oword).u32[3] = (((oword).u32[3] \
++ & ~EFX_INPLACE_MASK32(96, 127, field)) \
++ | EFX_INSERT_FIELD32(96, 127, field, value)); \
++ } while (0)
++
++#define EFX_SET_QWORD_FIELD32(qword, field, value) do { \
++ (qword).u32[0] = (((qword).u32[0] \
++ & ~EFX_INPLACE_MASK32(0, 31, field)) \
++ | EFX_INSERT_FIELD32(0, 31, field, value)); \
++ (qword).u32[1] = (((qword).u32[1] \
++ & ~EFX_INPLACE_MASK32(32, 63, field)) \
++ | EFX_INSERT_FIELD32(32, 63, field, value)); \
++ } while (0)
++
++#define EFX_SET_DWORD_FIELD(dword, field, value) do { \
++ (dword).u32[0] = (((dword).u32[0] \
++ & ~EFX_INPLACE_MASK32(0, 31, field)) \
++ | EFX_INSERT_FIELD32(0, 31, field, value)); \
++ } while (0)
++
++#if BITS_PER_LONG == 64
++#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD64
++#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD64
++#else
++#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD32
++#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD32
++#endif
++
++#define EFX_SET_OWORD_FIELD_VER(efx, oword, field, value) do { \
++ if (FALCON_REV(efx) == FALCON_REV_B0) { \
++ EFX_SET_OWORD_FIELD((oword), field##_B0, (value)); \
++ } else { \
++ EFX_SET_OWORD_FIELD((oword), field##_A1, (value)); \
++ } \
++} while (0)
++
++#define EFX_QWORD_FIELD_VER(efx, qword, field) \
++ (FALCON_REV(efx) == FALCON_REV_B0 ? \
++ EFX_QWORD_FIELD((qword), field##_B0) : \
++ EFX_QWORD_FIELD((qword), field##_A1))
++
++/* Used to avoid compiler warnings about shift range exceeding width
++ * of the data types when dma_addr_t is only 32 bits wide.
++ */
++#define DMA_ADDR_T_WIDTH (8 * sizeof(dma_addr_t))
++#define EFX_DMA_TYPE_WIDTH(width) \
++ (((width) < DMA_ADDR_T_WIDTH) ? (width) : DMA_ADDR_T_WIDTH)
++#define EFX_DMA_MAX_MASK ((DMA_ADDR_T_WIDTH == 64) ? \
++ ~((u64) 0) : ~((u32) 0))
++#define EFX_DMA_MASK(mask) ((mask) & EFX_DMA_MAX_MASK)
++
++/*
++ * Determine if a DMA address is over the 4GB threshold
++ *
++ * Defined in a slightly tortuous way to avoid compiler warnings.
++ */
++static inline int efx_is_over_4gb(dma_addr_t address)
++{
++ if (DMA_ADDR_T_WIDTH > 32)
++ return (((u64) address) >> 32) ? 1 : 0;
++ else
++ /* Can never be true */
++ return 0;
++}
++
++#endif /* EFX_BITFIELD_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/boards.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/boards.c
+--- linux-2.6.18.8/drivers/net/sfc/boards.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/boards.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,528 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "net_driver.h"
++#include "phy.h"
++#include "lm87_support.h"
++#include "boards.h"
++#include "efx.h"
++
++/* Macros for unpacking the board revision */
++/* The revision info is in host byte order. */
++#define BOARD_TYPE(_rev) (_rev >> 8)
++#define BOARD_MAJOR(_rev) ((_rev >> 4) & 0xf)
++#define BOARD_MINOR(_rev) (_rev & 0xf)
++
++/* Blink support. If the PHY has no auto-blink mode so we hang it off a timer */
++#define BLINK_INTERVAL (HZ/2)
++
++static void blink_led_timer(unsigned long context)
++{
++ struct efx_nic *efx = (struct efx_nic *)context;
++ struct efx_blinker *bl = &efx->board_info.blinker;
++ efx->board_info.set_fault_led(efx, bl->state);
++ bl->state = !bl->state;
++ if (bl->resubmit) {
++ bl->timer.expires = jiffies + BLINK_INTERVAL;
++ add_timer(&bl->timer);
++ }
++}
++
++static void board_blink(struct efx_nic *efx, int blink)
++{
++ struct efx_blinker *blinker = &efx->board_info.blinker;
++
++ /* The rtnl mutex serialises all ethtool ioctls, so
++ * nothing special needs doing here. */
++ if (blink) {
++ blinker->resubmit = 1;
++ blinker->state = 0;
++ setup_timer(&blinker->timer, blink_led_timer,
++ (unsigned long)efx);
++ blinker->timer.expires = jiffies + BLINK_INTERVAL;
++ add_timer(&blinker->timer);
++ } else {
++ blinker->resubmit = 0;
++ if (blinker->timer.function)
++ del_timer_sync(&blinker->timer);
++ efx->board_info.set_fault_led(efx, 0);
++ }
++}
++
++
++struct sensor_conf {
++ const char *name;
++ const unsigned high;
++ const unsigned low;
++};
++
++#define NO_LIMIT ((unsigned)-1)
++
++#define LM87_SENSOR_BYTES (18)
++
++static int sensor_limits_to_bytes(const struct sensor_conf *limits,
++ int nlimits, u8 *bytes, int maxbytes)
++{
++ int i, nbytes;
++ nbytes = 0;
++ for (i = 0; i < nlimits; i++) {
++ bytes[nbytes++] = limits[i].high;
++ if (limits[i].low != NO_LIMIT)
++ bytes[nbytes++] = limits[i].low;
++ /* We may have overrun by one at this point, but this test
++ * should only trigger in development drivers as the sizes
++ * are not dynamic. */
++ if (nbytes > maxbytes) {
++ printk(KERN_ERR "%s: out of space!\n", __func__);
++ break;
++ }
++ }
++ return nbytes;
++}
++
++/*****************************************************************************
++ * Support for the SFE4002
++ *
++ */
++/* LM87 configuration data for the sensor on the SFE4002 board */
++static const struct sensor_conf sfe4002_lm87_limits[] = {
++ {"1.8V line", 0x91, 0x83}, /* 2.5V sensor, scaled for 1.8V */
++ {"1.2V line", 0x5a, 0x51}, /* Vccp1 */
++ {"3.3V line", 0xca, 0xb6},
++ {"5V line", 0xc9, 0xb6},
++ {"12V line", 0xe0, 0xb0},
++ {"1V line", 0x4b, 0x44}, /* vccp2 */
++ {"Ext. temp.", 0x46, 0x0a}, /* ASIC temp. */
++ {"Int. temp.", 0x3c, 0x0a}, /* Board temp. */
++ {"1.66V line", 0xb2, NO_LIMIT}, /* AIN1 only takes 1 value */
++ {"1.5V line", 0xa1, NO_LIMIT} /* AIN2 only takes 1 value */
++};
++
++static const int sfe4002_lm87_nlimits = ARRAY_SIZE(sfe4002_lm87_limits);
++
++static u16 sfe4002_lm87_irq_mask = EFX_LM87_NO_INTS;
++
++/* I2C ID of the onboard LM87 chip. This is board-specific as the bottom two
++ * bits are set by strap pins */
++#define SFE4002_LM87_I2C_ID (0x2e)
++
++/****************************************************************************/
++/* LED allocations. Note that on rev A0 boards the schematic and the reality
++ * differ: red and green are swapped. Below is the fixed (A1) layout (there
++ * are only 3 A0 boards in existence, so no real reason to make this
++ * conditional).
++ */
++#define SFE4002_FAULT_LED (2) /* Red */
++#define SFE4002_RX_LED (0) /* Green */
++#define SFE4002_TX_LED (1) /* Amber */
++
++static int sfe4002_init_leds(struct efx_nic *efx)
++{
++ /* Set the TX and RX LEDs to reflect status and activity, and the
++ * fault LED off */
++ xfp_set_led(efx, SFE4002_TX_LED,
++ QUAKE_LED_TXLINK | QUAKE_LED_LINK_ACTSTAT);
++ xfp_set_led(efx, SFE4002_RX_LED,
++ QUAKE_LED_RXLINK | QUAKE_LED_LINK_ACTSTAT);
++ xfp_set_led(efx, SFE4002_FAULT_LED, QUAKE_LED_OFF);
++ efx->board_info.blinker.led_num = SFE4002_FAULT_LED;
++ return 0;
++}
++
++static void sfe4002_fault_led(struct efx_nic *efx, int state)
++{
++ xfp_set_led(efx, SFE4002_FAULT_LED, state ? QUAKE_LED_ON :
++ QUAKE_LED_OFF);
++}
++
++static int sfe4002_sensor_meaning(struct efx_nic *efx, int limit_num,
++ unsigned val)
++{
++ const struct sensor_conf *lim = &sfe4002_lm87_limits[limit_num];
++ if (lim->low == NO_LIMIT)
++ EFX_ERR(efx, "%10s 0x%02x (nominal value 0x%02x)\n", lim->name,
++ val, lim->high);
++ else
++ EFX_ERR(efx, "%10s 0x%02x (nominal range 0x%02x - 0x%02x)\n",
++ lim->name, val, lim->high, lim->low);
++ return 1;
++}
++
++static int sfe4002_check_hw(struct efx_nic *efx)
++{
++ int rc;
++
++ /* A0 board rev. 4002s report a temperature fault the whole time
++ * (bad sensor) so we mask it out. */
++ unsigned alarm_mask = (efx->board_info.minor > 0) ?
++ 0 : ~EFX_LM87_ETMP_INT;
++
++ /* Check the sensor (NOP if not present). */
++ rc = efx_check_lm87(efx, alarm_mask);
++
++ /* We treat both lm87 interrupts and failure to talk to the lm87
++ * as problems (since failure will only be reported if we did
++ * find the sensor at probe time. */
++ if (rc)
++ EFX_ERR(efx, "sensor alert!\n");
++ return rc;
++}
++
++static int sfe4002_init(struct efx_nic *efx)
++{
++ u8 lm87_bytes[LM87_SENSOR_BYTES];
++ int nbytes;
++ int rc;
++
++ efx->board_info.monitor = sfe4002_check_hw;
++ efx->board_info.interpret_sensor = sfe4002_sensor_meaning;
++ efx->board_info.init_leds = sfe4002_init_leds;
++ efx->board_info.set_fault_led = sfe4002_fault_led;
++ efx->board_info.blink = board_blink;
++ /* To clean up shut down the lm87 (NOP if not present) */
++ efx->board_info.fini = efx_remove_lm87;
++
++ nbytes = sensor_limits_to_bytes(sfe4002_lm87_limits,
++ sfe4002_lm87_nlimits, lm87_bytes,
++ LM87_SENSOR_BYTES);
++
++ /* Activate the lm87 sensor if present (succeeds if nothing there) */
++ rc = efx_probe_lm87(efx, SFE4002_LM87_I2C_ID,
++ lm87_bytes, nbytes, sfe4002_lm87_irq_mask);
++
++ return rc;
++}
++
++/*****************************************************************************
++ * Support for the SFE4003
++ *
++ */
++/* LM87 configuration data for the sensor on the SFE4003 board */
++static const struct sensor_conf sfe4003_lm87_limits[] = {
++ {"1.5V line", 0x78, 0x6d}, /* 2.5V input, values scaled for 1.5V */
++ {"1.2V line", 0x5a, 0x51}, /* Vccp1 */
++ {"3.3V line", 0xca, 0xb6},
++ {"5V line", 0xc0, 0x00}, /* Sensor not connected. */
++ {"12V line", 0xe0, 0xb0},
++ {"1V line", 0x4b, 0x44}, /* Vccp2 */
++ {"Ext. temp.", 0x46, 0x0a}, /* ASIC temp. */
++ {"Int. temp.", 0x3c, 0x0a}, /* Board temp. */
++ {"", 0xff, NO_LIMIT}, /* FAN1/AIN1 unused */
++ {"", 0xff, NO_LIMIT} /* FAN2/AIN2 unused */
++};
++
++static const int sfe4003_lm87_nlimits = ARRAY_SIZE(sfe4003_lm87_limits);
++
++static u16 sfe4003_lm87_irq_mask = EFX_LM87_NO_INTS;
++
++
++static int sfe4003_sensor_meaning(struct efx_nic *efx, int limit_num,
++ unsigned val)
++{
++ const struct sensor_conf *lim = &sfe4003_lm87_limits[limit_num];
++ if (lim->low == NO_LIMIT)
++ return 0; /* Neither AIN1 nor AIN2 mean anything to us */
++ else
++ EFX_ERR(efx, "%10s 0x%02x (nominal range 0x%02x - 0x%02x)\n",
++ lim->name, val, lim->high, lim->low);
++ return 1;
++}
++
++/* I2C ID of the onboard LM87 chip. This is board-specific as the bottom two
++ * bits are set by strap pins */
++#define SFE4003_LM87_I2C_ID (0x2e)
++
++/* Board-specific LED info. */
++#define SFE4003_RED_LED_GPIO (11)
++#define SFE4003_LED_ON (1)
++#define SFE4003_LED_OFF (0)
++
++static void sfe4003_fault_led(struct efx_nic *efx, int state)
++{
++ /* The LEDs were not wired to GPIOs before A3 */
++ if (efx->board_info.minor < 3 && efx->board_info.major == 0)
++ return;
++
++ txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO,
++ state ? SFE4003_LED_ON : SFE4003_LED_OFF);
++}
++
++static int sfe4003_init_leds(struct efx_nic *efx)
++{
++ /* The LEDs were not wired to GPIOs before A3 */
++ if (efx->board_info.minor < 3 && efx->board_info.major == 0)
++ return 0;
++
++ txc_set_gpio_dir(efx, SFE4003_RED_LED_GPIO, TXC_GPIO_DIR_OUTPUT);
++ txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO, SFE4003_LED_OFF);
++ return 0;
++}
++
++static int sfe4003_check_hw(struct efx_nic *efx)
++{
++ int rc;
++ /* A0/A1/A2 board rev. 4003s report a temperature fault the whole time
++ * (bad sensor) so we mask it out. */
++ unsigned alarm_mask =
++ ~(EFX_LM87_ETMP_INT | EFX_LM87_FAN1_INT | EFX_LM87_FAN2_INT);
++
++ /* Check the sensor (NOP if not present). */
++
++ rc = efx_check_lm87(efx, alarm_mask);
++ /* We treat both lm87 interrupts and failure to talk to the lm87
++ * as problems (since failure will only be reported if we did
++ * find the sensor at probe time. */
++ if (rc)
++ EFX_ERR(efx, "sensor alert!\n");
++
++ return rc;
++}
++
++static int sfe4003_init(struct efx_nic *efx)
++{
++ u8 lm87_bytes[LM87_SENSOR_BYTES];
++ int nbytes;
++ int rc;
++ efx->board_info.monitor = sfe4003_check_hw;
++ efx->board_info.interpret_sensor = sfe4003_sensor_meaning;
++ efx->board_info.init_leds = sfe4003_init_leds;
++ efx->board_info.set_fault_led = sfe4003_fault_led;
++ efx->board_info.blink = board_blink;
++ /* To clean up shut down the lm87 (NOP if not present) */
++ efx->board_info.fini = efx_remove_lm87;
++
++ nbytes = sensor_limits_to_bytes(sfe4003_lm87_limits,
++ sfe4003_lm87_nlimits, lm87_bytes,
++ LM87_SENSOR_BYTES);
++
++ /* Activate the lm87 sensor if present (succeeds if nothing there) */
++ rc = efx_probe_lm87(efx, SFE4003_LM87_I2C_ID,
++ lm87_bytes, nbytes, sfe4003_lm87_irq_mask);
++
++ if (rc < 0)
++ EFX_ERR(efx, "Temperature sensor probe failure: "
++ "please check the jumper position\n");
++ return rc;
++}
++
++/*****************************************************************************
++ * Support for the SFE4005
++ *
++ */
++/* LM87 configuration data for the sensor on the SFE4005 board */
++static const u8 sfe4005_lm87_limits[] = {
++ 0x51, /* 2.5V high lim. (actually monitor 1.0V line, so 1050mV) */
++ 0x49, /* 2.5V low lim. (950mV) */
++ 0xf6, /* Vccp1 high lim. (3.3V rail, 3465 mV) */
++ 0xde, /* Vcpp1 low lim. (3.3V rail, 3135 mV) */
++ 0xca, /* 3.3V AUX high lim. (3465 mV) */
++ 0xb6, /* 3.3V AUX low lim. (3135mV) */
++ 0xc0, /* 5V high lim. not connected) */
++ 0x00, /* 5V low lim. (not connected) */
++ 0xd0, /* 12V high lim. (13000mV) */
++ 0xb0, /* 12V low lim. (11000mV) */
++ 0xc0, /* Vccp2 high lim. (unused) */
++ 0x00, /* Vccp2 low lim. (unused) */
++ 0x46, /* Ext temp 1 (ASIC) high lim. */
++ 0x0a, /* Ext temp 1 low lim. */
++ 0x3c, /* Int temp (board) high lim. */
++ 0x0a, /* Int temp 1 low lim. */
++ 0xff, /* Fan 1 high (unused) */
++ 0xff, /* Fan 2 high (unused) */
++};
++
++#define SFE4005_LM87_I2C_ID (0x2e)
++
++/* Until the LM87 monitoring is interrupt driven. */
++#define SFE4005_LM87_IRQMASK EFX_LM87_NO_INTS
++
++#define SFE4005_PCF8575_I2C_ID (0x20)
++/* Definitions for the I/O expander that controls the CX4 chip:
++ * which PCF8575 pin maps to which function */
++#define SFE4005_PORT0_EXTLOOP (1 << 0)
++#define SFE4005_PORT1_EXTLOOP (1 << 1)
++#define SFE4005_HOSTPROT_LOOP (1 << 2)
++#define SFE4005_BCAST (1 << 3) /* TX on both ports */
++#define SFE4005_PORT0_EQ (1 << 4)
++#define SFE4005_PORT1_EQ (1 << 5)
++#define SFE4005_HOSTPORT_EQ (1 << 6)
++#define SFE4005_PORTSEL (1 << 7) /* Which port (for RX in BCAST mode) */
++#define SFE4005_PORT0_PRE_LBN (8) /* Preemphasis on port 0 (2 bits)*/
++#define SFE4005_PORT1_PRE_LBN (10) /* Preemphasis on port 1 (2 bits)*/
++#define SFE4005_HOSTPORT_PRE_LBN (12) /* Preemphasis on host port (2 bits) */
++#define SFE4005_UNUSED (1 << 14)
++#define SFE4005_CX4uC_nRESET (1 << 15) /* Reset the controller on CX4 chip */
++
++
++/* By default only turn on host port EQ. Can also OR in SFE4005_PORT0_EQ,
++ * SFE4005_PORT1_EQ but this hasn't been seen to make a difference. */
++#define SFE4005_CX4_DEFAULTS (SFE4005_CX4uC_nRESET | SFE4005_HOSTPORT_EQ)
++
++static int sfe4005_write_ioexpander(struct efx_nic *efx)
++{
++ unsigned long iobits = (unsigned long)efx->phy_data;
++ struct efx_i2c_interface *i2c = &efx->i2c;
++ u8 send[2], check[2];
++ int rc;
++ /* Do not, EVER, deassert nRESET as that will reset Falcon too,
++ * and the driver won't know to repush the configuration, so
++ * nothing will work until the next power cycle. */
++ BUG_ON(!(iobits & SFE4005_CX4uC_nRESET));
++ send[0] = (iobits & 0xff);
++ send[1] = ((iobits >> 8) & 0xff);
++ rc = efx_i2c_send_bytes(i2c, SFE4005_PCF8575_I2C_ID, send, 2);
++ if (rc) {
++ EFX_ERR(efx, "failed to write to I/O expander: %d\n", rc);
++ return rc;
++ }
++ /* Paranoia: just check what the I/O expander reads back */
++ rc = efx_i2c_recv_bytes(i2c, SFE4005_PCF8575_I2C_ID, check, 2);
++ if (rc)
++ EFX_ERR(efx, "failed to read back from I/O expander: %d\n", rc);
++ else if (check[0] != send[0] || check[1] != send[1])
++ EFX_ERR(efx, "read back wrong value from I/O expander: "
++ "wanted %.2x%.2x, got %.2x%.2x\n",
++ send[1], send[0], check[1], check[0]);
++ return rc;
++}
++
++static int sfe4005_init(struct efx_nic *efx)
++{
++ unsigned long iobits = SFE4005_CX4_DEFAULTS;
++ int rc;
++
++ /* There is no PHY as such on the SFE4005 so phy_data is ours. */
++ efx->phy_data = (void *)iobits;
++
++ /* Push the values */
++ rc = sfe4005_write_ioexpander(efx);
++ if (rc)
++ return rc;
++
++ /* Activate the lm87 sensor if present (succeeds if nothing there) */
++ rc = efx_probe_lm87(efx, SFE4005_LM87_I2C_ID,
++ sfe4005_lm87_limits,
++ sizeof(sfe4005_lm87_limits), SFE4005_LM87_IRQMASK);
++
++ /* To clean up shut down the lm87 (NOP if not present) */
++ efx->board_info.fini = efx_remove_lm87;
++
++ return rc;
++}
++
++/* This will get expanded as board-specific details get moved out of the
++ * PHY drivers. */
++struct efx_board_data {
++ const char *ref_model;
++ const char *gen_type;
++ int (*init) (struct efx_nic *nic);
++ unsigned mwatts;
++};
++
++static void dummy_fini(struct efx_nic *nic)
++{
++}
++
++static int dummy_init(struct efx_nic *nic)
++{
++ nic->board_info.fini = dummy_fini;
++ return 0;
++}
++
++/* Maximum board power (mW)
++ * Falcon controller ASIC accounts for 2.2W
++ * 10Xpress PHY accounts for 12W
++ *
++ */
++#define SFE4001_POWER 18000
++#define SFE4002_POWER 7500
++#define SFE4003_POWER 4500
++#define SFE4005_POWER 4500
++
++static struct efx_board_data board_data[] = {
++ [EFX_BOARD_INVALID] =
++ {NULL, NULL, dummy_init, 0},
++ [EFX_BOARD_SFE4001] =
++ {"SFE4001", "10GBASE-T adapter", sfe4001_poweron, SFE4001_POWER },
++ [EFX_BOARD_SFE4002] =
++ {"SFE4002", "XFP adapter", sfe4002_init, SFE4002_POWER },
++ [EFX_BOARD_SFE4003] =
++ {"SFE4003", "10GBASE-CX4 adapter", sfe4003_init, SFE4003_POWER },
++ [EFX_BOARD_SFE4005] =
++ {"SFE4005", "10G blade adapter", sfe4005_init, SFE4005_POWER },
++};
++
++int efx_set_board_info(struct efx_nic *efx, u16 revision_info)
++{
++ int rc = 0;
++ struct efx_board_data *data;
++
++ if (BOARD_TYPE(revision_info) >= EFX_BOARD_MAX) {
++ EFX_ERR(efx, "squashing unknown board type %d\n",
++ BOARD_TYPE(revision_info));
++ revision_info = 0;
++ }
++
++ if (BOARD_TYPE(revision_info) == 0) {
++ efx->board_info.major = 0;
++ efx->board_info.minor = 0;
++ /* For early boards that don't have revision info. there is
++ * only 1 board for each PHY type, so we can work it out, with
++ * the exception of the PHY-less boards. */
++ switch (efx->phy_type) {
++ case PHY_TYPE_10XPRESS:
++ efx->board_info.type = EFX_BOARD_SFE4001;
++ break;
++ case PHY_TYPE_XFP:
++ efx->board_info.type = EFX_BOARD_SFE4002;
++ break;
++ case PHY_TYPE_CX4_RTMR:
++ efx->board_info.type = EFX_BOARD_SFE4003;
++ break;
++ default:
++ efx->board_info.type = 0;
++ break;
++ }
++ } else {
++ efx->board_info.type = BOARD_TYPE(revision_info);
++ efx->board_info.major = BOARD_MAJOR(revision_info);
++ efx->board_info.minor = BOARD_MINOR(revision_info);
++ }
++
++ data = &board_data[efx->board_info.type];
++
++ /* Report the board model number or generic type for recognisable
++ * boards. */
++ if (efx->board_info.type != 0)
++ EFX_INFO(efx, "board is %s rev %c%d\n",
++ (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
++ ? data->ref_model : data->gen_type,
++ 'A' + efx->board_info.major, efx->board_info.minor);
++
++ efx->board_info.init = data->init;
++ efx->board_info.mwatts = data->mwatts;
++
++ return rc;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/boards.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/boards.h
+--- linux-2.6.18.8/drivers/net/sfc/boards.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/boards.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,51 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_BOARDS_H
++#define EFX_BOARDS_H
++
++/* Board IDs (must fit in 8 bits). Note that 0 must never be assigned because
++ * on early boards it means there is no revision info. Board types pre 400x
++ * are not covered here, but this is not a problem because:
++ * - the early Falcon boards (FPGA, 401, 403) don't have any extra H/W we
++ * need care about and aren't being updated.
++ */
++enum efx_board_type {
++ EFX_BOARD_INVALID = 0, /* Early boards do not have board rev. info. */
++ EFX_BOARD_SFE4001 = 1,
++ EFX_BOARD_SFE4002 = 2,
++ EFX_BOARD_SFE4003 = 3,
++ EFX_BOARD_SFE4005 = 4,
++ /* Insert new types before here */
++ EFX_BOARD_MAX
++};
++
++extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info);
++
++/* SFE4001 (10GBASE-T) */
++extern int sfe4001_poweron(struct efx_nic *efx);
++extern void sfe4001_poweroff(struct efx_nic *efx);
++
++#endif
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/config.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/config.h
+--- linux-2.6.18.8/drivers/net/sfc/config.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/config.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1 @@
++/* SFC config options can go here */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/debugfs.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/debugfs.c
+--- linux-2.6.18.8/drivers/net/sfc/debugfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/debugfs.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,924 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/module.h>
++#include <linux/pci.h>
++/* For out-of-tree builds we always need procfs, if only for a compatibility
++ * symlink.
++ */
++#include <linux/proc_fs.h>
++#include <linux/dcache.h>
++#include <linux/seq_file.h>
++#include "net_driver.h"
++#include "efx.h"
++#include "debugfs.h"
++#include "falcon.h"
++
++/* EFX_USE_DEBUGFS is defined by kernel_compat.h so we can't decide whether to
++ * include this earlier.
++ */
++#ifdef EFX_USE_DEBUGFS
++#include <linux/debugfs.h>
++#endif
++
++#ifndef PRIu64
++# if (BITS_PER_LONG == 64)
++# define PRIu64 "lu"
++# else
++# define PRIu64 "llu"
++# endif
++#endif
++
++#ifndef EFX_USE_DEBUGFS
++
++static void efx_debugfs_remove(struct proc_dir_entry *entry)
++{
++ if (entry)
++ remove_proc_entry(entry->name, entry->parent);
++}
++#define debugfs_remove efx_debugfs_remove
++
++#define debugfs_create_dir proc_mkdir
++#define debugfs_create_symlink proc_symlink
++
++#endif /* !EFX_USE_DEBUGFS */
++
++/* Parameter definition bound to a structure - each file has one of these */
++struct efx_debugfs_bound_param {
++ const struct efx_debugfs_parameter *param;
++ void *structure;
++};
++
++
++/* Maximum length for a name component or symlink target */
++#define EFX_DEBUGFS_NAME_LEN 32
++
++
++/* Top-level debug directory ([/sys/kernel]/debug/sfc) */
++static struct dentry *efx_debug_root;
++
++/* "cards" directory ([/sys/kernel]/debug/sfc/cards) */
++static struct dentry *efx_debug_cards;
++
++
++/* Sequential file interface to bound parameters */
++
++#if defined(EFX_USE_DEBUGFS)
++
++static int efx_debugfs_seq_show(struct seq_file *file, void *v)
++{
++ struct efx_debugfs_bound_param *binding =
++ (struct efx_debugfs_bound_param *)file->private;
++
++ return binding->param->reader(file,
++ binding->structure +
++ binding->param->offset);
++}
++
++static int efx_debugfs_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, efx_debugfs_seq_show, inode->i_private);
++}
++
++#else /* EFX_NOT_UPSTREAM && !EFX_USE_DEBUGFS */
++
++static int efx_debugfs_seq_show(struct seq_file *file, void *v)
++{
++ struct proc_dir_entry *entry = (struct proc_dir_entry *)file->private;
++ struct efx_debugfs_parameter *param =
++ (struct efx_debugfs_parameter *)entry->data;
++ void *structure = (void *)entry->read_proc;
++
++ if (!structure)
++ return -EIO;
++
++ return param->reader(file, structure + param->offset);
++}
++
++static int efx_debugfs_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, efx_debugfs_seq_show, PROC_I(inode)->pde);
++}
++
++#endif /* !EFX_NOT_UPSTREAM || EFX_USE_DEBUGFS */
++
++
++static struct file_operations efx_debugfs_file_ops = {
++ .owner = THIS_MODULE,
++ .open = efx_debugfs_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release
++};
++
++
++#if defined(EFX_USE_DEBUGFS)
++
++/**
++ * efx_fini_debugfs_child - remove a named child of a debugfs directory
++ * @dir: Directory
++ * @name: Name of child
++ *
++ * This removes the named child from the directory, if it exists.
++ */
++void efx_fini_debugfs_child(struct dentry *dir, const char *name)
++{
++ struct qstr child_name;
++ struct dentry *child;
++
++ child_name.len = strlen(name);
++ child_name.name = name;
++ child_name.hash = full_name_hash(child_name.name, child_name.len);
++ child = d_lookup(dir, &child_name);
++ if (child) {
++ /* If it's a "regular" file, free its parameter binding */
++ if (S_ISREG(child->d_inode->i_mode))
++ kfree(child->d_inode->i_private);
++ debugfs_remove(child);
++ dput(child);
++ }
++}
++
++#else /* EFX_NOT_UPSTREAM && !EFX_USE_DEBUGFS */
++
++void efx_fini_debugfs_child(struct proc_dir_entry *dir, const char *name)
++{
++ remove_proc_entry(name, dir);
++}
++
++#endif /* !EFX_NOT_UPSTREAM || EFX_USE_DEBUGFS */
++
++/*
++ * Remove a debugfs directory.
++ *
++ * This removes the named parameter-files and sym-links from the
++ * directory, and the directory itself. It does not do any recursion
++ * to subdirectories.
++ */
++static void efx_fini_debugfs_dir(struct dentry *dir,
++ struct efx_debugfs_parameter *params,
++ const char *const *symlink_names)
++{
++ if (!dir)
++ return;
++
++ while (params->name) {
++ efx_fini_debugfs_child(dir, params->name);
++ params++;
++ }
++ while (symlink_names && *symlink_names) {
++ efx_fini_debugfs_child(dir, *symlink_names);
++ symlink_names++;
++ }
++ debugfs_remove(dir);
++}
++
++/* Functions for printing various types of parameter. */
++
++int efx_debugfs_read_uint(struct seq_file *file, void *data)
++{
++ return seq_printf(file, "%#x\n", *(unsigned int *)data);
++}
++
++int efx_debugfs_read_int(struct seq_file *file, void *data)
++{
++ return seq_printf(file, "%d\n", *(int *)data);
++}
++
++int efx_debugfs_read_atomic(struct seq_file *file, void *data)
++{
++ unsigned int value = atomic_read((atomic_t *) data);
++
++ return seq_printf(file, "%#x\n", value);
++}
++
++int efx_debugfs_read_dword(struct seq_file *file, void *data)
++{
++ unsigned int value = EFX_DWORD_FIELD(*(efx_dword_t *) data,
++ EFX_DWORD_0);
++
++ return seq_printf(file, "%#x\n", value);
++}
++
++static int efx_debugfs_read_int_mode(struct seq_file *file, void *data)
++{
++ unsigned int value = *(enum efx_int_mode *) data;
++
++ return seq_printf(file, "%d => %s\n", value,
++ STRING_TABLE_LOOKUP(value, efx_interrupt_mode));
++}
++
++#define EFX_INT_MODE_PARAMETER(container_type, parameter) \
++ EFX_PARAMETER(container_type, parameter, \
++ enum efx_int_mode, efx_debugfs_read_int_mode)
++
++static int efx_debugfs_read_loop_mode(struct seq_file *file, void *data)
++{
++ unsigned int value = *(enum efx_loopback_mode *)data;
++
++ return seq_printf(file, "%d => %s\n", value,
++ STRING_TABLE_LOOKUP(value, efx_loopback_mode));
++}
++
++#define EFX_LOOPBACK_MODE_PARAMETER(container_type, parameter) \
++ EFX_PARAMETER(container_type, parameter, \
++ enum efx_loopback_mode, efx_debugfs_read_loop_mode)
++
++static int efx_debugfs_read_phy_type(struct seq_file *file, void *data)
++{
++ unsigned int value = *(enum phy_type *) data;
++
++ return seq_printf(file, "%d => %s\n", value,
++ STRING_TABLE_LOOKUP(value, efx_phy_type));
++}
++
++#define EFX_PHY_TYPE_PARAMETER(container_type, parameter) \
++ EFX_PARAMETER(container_type, parameter, \
++ enum phy_type, efx_debugfs_read_phy_type)
++
++int efx_debugfs_read_string(struct seq_file *file, void *data)
++{
++ return seq_puts(file, (const char *)data);
++}
++
++
++/**
++ * efx_init_debugfs_files - create parameter-files in a debugfs directory
++ * @parent: Containing directory
++ * @params: Pointer to zero-terminated parameter definition array
++ * @structure: Structure containing parameters
++ *
++ * Add parameter-files to the given debugfs directory. Return a
++ * negative error code or 0 on success.
++ */
++static int efx_init_debugfs_files(struct dentry *parent,
++ struct efx_debugfs_parameter *params,
++ void *structure)
++{
++ struct efx_debugfs_parameter *param = params;
++
++ while (param->name) {
++ struct dentry *entry;
++#if defined(EFX_USE_DEBUGFS)
++ struct efx_debugfs_bound_param *binding;
++
++ binding = kmalloc(sizeof(*binding), GFP_KERNEL);
++ if (!binding)
++ goto err;
++ binding->param = param;
++ binding->structure = structure;
++
++ entry = debugfs_create_file(param->name, S_IRUGO, parent,
++ binding, &efx_debugfs_file_ops);
++ if (!entry) {
++ kfree(binding);
++ goto err;
++ }
++#else
++ entry = create_proc_entry(param->name, S_IRUGO, parent);
++ if (!entry)
++ goto err;
++ /*
++ * We have no good way to free a binding created here.
++ * However, once we install our file_operations the
++ * read_proc pointer becomes redundant and we can
++ * abuse it as a structure pointer.
++ */
++ entry->data = param;
++ entry->read_proc = NULL;
++ smp_wmb();
++ entry->proc_fops = &efx_debugfs_file_ops;
++ smp_wmb();
++ entry->read_proc = (read_proc_t *) structure;
++#endif
++
++ param++;
++ }
++
++ return 0;
++
++ err:
++ while (param != params) {
++ param--;
++ efx_fini_debugfs_child(parent, param->name);
++ }
++ return -ENOMEM;
++}
++
++/**
++ * efx_init_debugfs_netdev - create debugfs sym-links for net device
++ * @net_dev: Net device
++ *
++ * Create sym-links named after @net_dev to the debugfs directories for
++ * the corresponding NIC and port. Return a negative error code or 0 on
++ * success. The sym-links must be cleaned up using
++ * efx_fini_debugfs_netdev().
++ */
++int efx_init_debugfs_netdev(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ char name[EFX_DEBUGFS_NAME_LEN];
++ char target[EFX_DEBUGFS_NAME_LEN];
++ size_t len;
++
++ if (snprintf(name, sizeof(name), "nic_%s", net_dev->name) >=
++ sizeof(name))
++ return -ENAMETOOLONG;
++ if (snprintf(target, sizeof(target), "cards/%s", pci_name(efx->pci_dev))
++ >= sizeof(target))
++ return -ENAMETOOLONG;
++ efx->debug_symlink = debugfs_create_symlink(name,
++ efx_debug_root, target);
++ if (!efx->debug_symlink)
++ return -ENOMEM;
++
++ if (snprintf(name, sizeof(name), "if_%s", net_dev->name) >=
++ sizeof(name))
++ return -ENAMETOOLONG;
++ len = snprintf(target, sizeof(target),
++ "cards/%s/port0", pci_name(efx->pci_dev));
++ if (len >= sizeof(target))
++ return -ENAMETOOLONG;
++ efx->debug_port_symlink = debugfs_create_symlink(name,
++ efx_debug_root,
++ target);
++ if (!efx->debug_port_symlink)
++ return -ENOMEM;
++
++ return 0;
++}
++
++/**
++ * efx_fini_debugfs_netdev - remove debugfs sym-links for net device
++ * @net_dev: Net device
++ *
++ * Remove sym-links created for @net_dev by efx_init_debugfs_netdev().
++ */
++void efx_fini_debugfs_netdev(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ debugfs_remove(efx->debug_port_symlink);
++ efx->debug_port_symlink = NULL;
++ debugfs_remove(efx->debug_symlink);
++ efx->debug_symlink = NULL;
++}
++
++/* Per-port parameters */
++static struct efx_debugfs_parameter efx_debugfs_port_parameters[] = {
++ EFX_NAMED_PARAMETER(enabled, struct efx_nic, port_enabled,
++ int, efx_debugfs_read_int),
++ EFX_INT_PARAMETER(struct efx_nic, net_dev_registered),
++ EFX_INT_PARAMETER(struct efx_nic, rx_checksum_enabled),
++ EFX_ATOMIC_PARAMETER(struct efx_nic, netif_stop_count),
++ EFX_INT_PARAMETER(struct efx_nic, link_up),
++ EFX_UINT_PARAMETER(struct efx_nic, link_options),
++ EFX_INT_PARAMETER(struct efx_nic, promiscuous),
++ EFX_UINT_PARAMETER(struct efx_nic, loopback_modes),
++ EFX_LOOPBACK_MODE_PARAMETER(struct efx_nic, loopback_mode),
++ EFX_PHY_TYPE_PARAMETER(struct efx_nic, phy_type),
++ EFX_NAMED_PARAMETER(phy_id, struct efx_nic, mii.phy_id,
++ int, efx_debugfs_read_int),
++ EFX_UINT_PARAMETER(struct efx_nic, n_link_state_changes),
++ {NULL},
++};
++
++/**
++ * efx_init_debugfs_port - create debugfs directory for port
++ * @efx: Efx NIC
++ *
++ * Create a debugfs directory containing parameter-files for @efx.
++ * Return a negative error code or 0 on success. The directory must be
++ * cleaned up using efx_fini_debugfs_port().
++ */
++int efx_init_debugfs_port(struct efx_nic *efx)
++{
++ int rc;
++
++ /* Create directory */
++ efx->debug_port_dir = debugfs_create_dir("port0", efx->debug_dir);
++ if (!efx->debug_port_dir)
++ return -ENOMEM;
++
++ /* Create files */
++ rc = efx_init_debugfs_files(efx->debug_port_dir,
++ efx_debugfs_port_parameters,
++ (void *)efx);
++ if (rc)
++ efx_fini_debugfs_port(efx);
++
++ return rc;
++}
++
++/**
++ * efx_fini_debugfs_port - remove debugfs directory for port
++ * @efx: Efx NIC
++ *
++ * Remove directory created for @efx by efx_init_debugfs_port().
++ */
++void efx_fini_debugfs_port(struct efx_nic *efx)
++{
++ efx_fini_debugfs_dir(efx->debug_port_dir,
++ efx_debugfs_port_parameters, NULL);
++ efx->debug_port_dir = NULL;
++}
++
++/**
++ * efx_extend_debugfs_port - add parameter-files to directory for port
++ * @efx: Efx NIC
++ * @structure: Structure containing parameters
++ * @params: Pointer to zero-terminated parameter definition array
++ *
++ * Add parameter-files to the debugfs directory for @efx. Return
++ * a negative error code or 0 on success. This is intended for
++ * PHY-specific parameters. The files must be cleaned up using
++ * efx_trim_debugfs_port().
++ */
++int efx_extend_debugfs_port(struct efx_nic *efx,
++ void *structure,
++ struct efx_debugfs_parameter *params)
++{
++ return efx_init_debugfs_files(efx->debug_port_dir, params, structure);
++}
++
++/**
++ * efx_trim_debugfs_port - remove parameter-files from directory for port
++ * @efx: Efx NIC
++ * @params: Pointer to zero-terminated parameter definition array
++ *
++ * Remove parameter-files previously added to the debugfs directory
++ * for @efx using efx_extend_debugfs_port().
++ */
++void efx_trim_debugfs_port(struct efx_nic *efx,
++ struct efx_debugfs_parameter *params)
++{
++ struct dentry *dir = efx->debug_port_dir;
++
++ if (dir) {
++ struct efx_debugfs_parameter *field;
++ for (field = params; field->name; field++)
++ efx_fini_debugfs_child(dir, field->name);
++ }
++}
++
++/* Per-TX-queue parameters */
++static struct efx_debugfs_parameter efx_debugfs_tx_queue_parameters[] = {
++ EFX_UINT_PARAMETER(struct efx_tx_queue, insert_count),
++ EFX_UINT_PARAMETER(struct efx_tx_queue, write_count),
++ EFX_UINT_PARAMETER(struct efx_tx_queue, read_count),
++ EFX_INT_PARAMETER(struct efx_tx_queue, stopped),
++ {NULL},
++};
++
++static void efx_fini_debugfs_tx_queue(struct efx_tx_queue *tx_queue);
++
++/**
++ * efx_init_debugfs_tx_queue - create debugfs directory for TX queue
++ * @tx_queue: Efx TX queue
++ *
++ * Create a debugfs directory containing parameter-files for @tx_queue.
++ * Return a negative error code or 0 on success. The directory must be
++ * cleaned up using efx_fini_debugfs_tx_queue().
++ */
++static int efx_init_debugfs_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ char name[EFX_DEBUGFS_NAME_LEN];
++ char target[EFX_DEBUGFS_NAME_LEN];
++ int rc;
++
++ /* Create directory */
++ if (snprintf(name, sizeof(name), EFX_TX_QUEUE_NAME(tx_queue))
++ >= sizeof(name))
++ goto err_len;
++ tx_queue->debug_dir = debugfs_create_dir(name,
++ tx_queue->efx->debug_dir);
++ if (!tx_queue->debug_dir)
++ goto err_mem;
++
++ /* Create files */
++ rc = efx_init_debugfs_files(tx_queue->debug_dir,
++ efx_debugfs_tx_queue_parameters,
++ (void *)tx_queue);
++ if (rc)
++ goto err;
++
++ /* Create symlink to channel */
++ if (snprintf(target, sizeof(target),
++ "../" EFX_CHANNEL_NAME(tx_queue->channel)) >=
++ sizeof(target))
++ goto err_len;
++ if (!debugfs_create_symlink("channel", tx_queue->debug_dir, target))
++ goto err_mem;
++
++ /* Create symlink to port */
++ if (!debugfs_create_symlink("port", tx_queue->debug_dir, "../port0"))
++ goto err_mem;
++
++ return 0;
++
++ err_len:
++ rc = -ENAMETOOLONG;
++ goto err;
++ err_mem:
++ rc = -ENOMEM;
++ err:
++ efx_fini_debugfs_tx_queue(tx_queue);
++ return rc;
++}
++
++/**
++ * efx_fini_debugfs_tx_queue - remove debugfs directory for TX queue
++ * @tx_queue: Efx TX queue
++ *
++ * Remove directory created for @tx_queue by efx_init_debugfs_tx_queue().
++ */
++static void efx_fini_debugfs_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ static const char *const symlink_names[] = {
++ "channel", "port", NULL
++ };
++
++ efx_fini_debugfs_dir(tx_queue->debug_dir,
++ efx_debugfs_tx_queue_parameters, symlink_names);
++ tx_queue->debug_dir = NULL;
++}
++
++/* Per-RX-queue parameters */
++static struct efx_debugfs_parameter efx_debugfs_rx_queue_parameters[] = {
++ EFX_INT_PARAMETER(struct efx_rx_queue, added_count),
++ EFX_INT_PARAMETER(struct efx_rx_queue, removed_count),
++ EFX_UINT_PARAMETER(struct efx_rx_queue, max_fill),
++ EFX_UINT_PARAMETER(struct efx_rx_queue, fast_fill_trigger),
++ EFX_UINT_PARAMETER(struct efx_rx_queue, fast_fill_limit),
++ EFX_UINT_PARAMETER(struct efx_rx_queue, min_fill),
++ EFX_UINT_PARAMETER(struct efx_rx_queue, min_overfill),
++ EFX_UINT_PARAMETER(struct efx_rx_queue, alloc_page_count),
++ EFX_UINT_PARAMETER(struct efx_rx_queue, alloc_skb_count),
++ EFX_UINT_PARAMETER(struct efx_rx_queue, slow_fill_count),
++ {NULL},
++};
++
++static void efx_fini_debugfs_rx_queue(struct efx_rx_queue *rx_queue);
++
++/**
++ * efx_init_debugfs_rx_queue - create debugfs directory for RX queue
++ * @rx_queue: Efx RX queue
++ *
++ * Create a debugfs directory containing parameter-files for @rx_queue.
++ * Return a negative error code or 0 on success. The directory must be
++ * cleaned up using efx_fini_debugfs_rx_queue().
++ */
++static int efx_init_debugfs_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ char name[EFX_DEBUGFS_NAME_LEN];
++ char target[EFX_DEBUGFS_NAME_LEN];
++ int rc;
++
++ /* Create directory */
++ if (snprintf(name, sizeof(name), EFX_RX_QUEUE_NAME(rx_queue))
++ >= sizeof(name))
++ goto err_len;
++ rx_queue->debug_dir = debugfs_create_dir(name,
++ rx_queue->efx->debug_dir);
++ if (!rx_queue->debug_dir)
++ goto err_mem;
++
++ /* Create files */
++ rc = efx_init_debugfs_files(rx_queue->debug_dir,
++ efx_debugfs_rx_queue_parameters,
++ (void *)rx_queue);
++ if (rc)
++ goto err;
++
++ /* Create symlink to channel */
++ if (snprintf(target, sizeof(target),
++ "../" EFX_CHANNEL_NAME(rx_queue->channel)) >=
++ sizeof(target))
++ goto err_len;
++ if (!debugfs_create_symlink("channel", rx_queue->debug_dir, target))
++ goto err_mem;
++
++ return 0;
++
++ err_len:
++ rc = -ENAMETOOLONG;
++ goto err;
++ err_mem:
++ rc = -ENOMEM;
++ err:
++ efx_fini_debugfs_rx_queue(rx_queue);
++ return rc;
++}
++
++/**
++ * efx_fini_debugfs_rx_queue - remove debugfs directory for RX queue
++ * @rx_queue: Efx RX queue
++ *
++ * Remove directory created for @rx_queue by efx_init_debugfs_rx_queue().
++ */
++static void efx_fini_debugfs_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ const char *const symlink_names[] = {
++ "channel", NULL
++ };
++
++ efx_fini_debugfs_dir(rx_queue->debug_dir,
++ efx_debugfs_rx_queue_parameters, symlink_names);
++ rx_queue->debug_dir = NULL;
++}
++
++/* Per-channel parameters */
++static struct efx_debugfs_parameter efx_debugfs_channel_parameters[] = {
++ EFX_INT_PARAMETER(struct efx_channel, enabled),
++ EFX_INT_PARAMETER(struct efx_channel, irq),
++ EFX_UINT_PARAMETER(struct efx_channel, has_interrupt),
++ EFX_UINT_PARAMETER(struct efx_channel, irq_moderation),
++ EFX_UINT_PARAMETER(struct efx_channel, eventq_read_ptr),
++ EFX_UINT_PARAMETER(struct efx_channel, n_rx_tobe_disc),
++ EFX_UINT_PARAMETER(struct efx_channel, n_rx_ip_frag_err),
++ EFX_UINT_PARAMETER(struct efx_channel, n_rx_ip_hdr_chksum_err),
++ EFX_UINT_PARAMETER(struct efx_channel, n_rx_tcp_udp_chksum_err),
++ EFX_UINT_PARAMETER(struct efx_channel, n_rx_frm_trunc),
++ EFX_UINT_PARAMETER(struct efx_channel, n_rx_overlength),
++ EFX_UINT_PARAMETER(struct efx_channel, n_skbuff_leaks),
++ EFX_INT_PARAMETER(struct efx_channel, rx_alloc_level),
++ EFX_INT_PARAMETER(struct efx_channel, rx_alloc_push_pages),
++ EFX_INT_PARAMETER(struct efx_channel, rx_alloc_pop_pages),
++ {NULL},
++};
++
++static void efx_fini_debugfs_channel(struct efx_channel *channel);
++
++/**
++ * efx_init_debugfs_channel - create debugfs directory for channel
++ * @channel: Efx channel
++ *
++ * Create a debugfs directory containing parameter-files for @channel.
++ * Return a negative error code or 0 on success. The directory must be
++ * cleaned up using efx_fini_debugfs_channel().
++ */
++static int efx_init_debugfs_channel(struct efx_channel *channel)
++{
++ char name[EFX_DEBUGFS_NAME_LEN];
++ int rc;
++
++ /* Create directory */
++ if (snprintf(name, sizeof(name), EFX_CHANNEL_NAME(channel))
++ >= sizeof(name))
++ goto err_len;
++ channel->debug_dir = debugfs_create_dir(name, channel->efx->debug_dir);
++ if (!channel->debug_dir)
++ goto err_mem;
++
++ /* Create files */
++ rc = efx_init_debugfs_files(channel->debug_dir,
++ efx_debugfs_channel_parameters,
++ (void *)channel);
++ if (rc)
++ goto err;
++
++ return 0;
++
++ err_len:
++ rc = -ENAMETOOLONG;
++ goto err;
++ err_mem:
++ rc = -ENOMEM;
++ err:
++ efx_fini_debugfs_channel(channel);
++ return rc;
++}
++
++/**
++ * efx_fini_debugfs_channel - remove debugfs directory for channel
++ * @channel: Efx channel
++ *
++ * Remove directory created for @channel by efx_init_debugfs_channel().
++ */
++static void efx_fini_debugfs_channel(struct efx_channel *channel)
++{
++ efx_fini_debugfs_dir(channel->debug_dir,
++ efx_debugfs_channel_parameters, NULL);
++ channel->debug_dir = NULL;
++}
++
++/* Per-NIC parameters */
++static struct efx_debugfs_parameter efx_debugfs_nic_parameters[] = {
++ EFX_INT_PARAMETER(struct efx_nic, legacy_irq),
++ EFX_INT_PARAMETER(struct efx_nic, rss_queues),
++ EFX_UINT_PARAMETER(struct efx_nic, rx_buffer_len),
++ EFX_INT_MODE_PARAMETER(struct efx_nic, interrupt_mode),
++ {.name = "hardware_desc",
++ .offset = 0,
++ .reader = falcon_debugfs_read_hardware_desc},
++ {NULL},
++};
++
++/* Per-NIC error counts */
++static struct efx_debugfs_parameter efx_debugfs_nic_error_parameters[] = {
++ EFX_ATOMIC_PARAMETER(struct efx_nic_errors, missing_event),
++ EFX_ATOMIC_PARAMETER(struct efx_nic_errors, rx_reset),
++ EFX_ATOMIC_PARAMETER(struct efx_nic_errors, rx_desc_fetch),
++ EFX_ATOMIC_PARAMETER(struct efx_nic_errors, tx_desc_fetch),
++ EFX_ATOMIC_PARAMETER(struct efx_nic_errors, spurious_tx),
++ {NULL},
++};
++
++/**
++ * efx_init_debugfs_channels - create debugfs directories for NIC channels
++ * @efx: Efx NIC
++ *
++ * Create subdirectories of @efx's debugfs directory for all the
++ * channels, RX queues and TX queues used by this driver. Return a
++ * negative error code or 0 on success. The subdirectories must be
++ * cleaned up using efx_fini_debugfs_channels().
++ */
++int efx_init_debugfs_channels(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ struct efx_rx_queue *rx_queue;
++ struct efx_tx_queue *tx_queue;
++ int rc;
++
++ efx_for_each_channel(channel, efx) {
++ rc = efx_init_debugfs_channel(channel);
++ if (rc)
++ goto err;
++ }
++
++ efx_for_each_rx_queue(rx_queue, efx) {
++ rc = efx_init_debugfs_rx_queue(rx_queue);
++ if (rc)
++ goto err;
++ }
++
++ efx_for_each_tx_queue(tx_queue, efx) {
++ rc = efx_init_debugfs_tx_queue(tx_queue);
++ if (rc)
++ goto err;
++ }
++
++ return 0;
++
++ err:
++ efx_fini_debugfs_channels(efx);
++ return rc;
++}
++
++/**
++ * efx_fini_debugfs_channels - remove debugfs directories for NIC queues
++ * @efx: Efx NIC
++ *
++ * Remove subdirectories of @efx's debugfs directory created by
++ * efx_init_debugfs_channels().
++ */
++void efx_fini_debugfs_channels(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ struct efx_rx_queue *rx_queue;
++ struct efx_tx_queue *tx_queue;
++
++ efx_for_each_tx_queue(tx_queue, efx)
++ efx_fini_debugfs_tx_queue(tx_queue);
++
++ efx_for_each_rx_queue(rx_queue, efx)
++ efx_fini_debugfs_rx_queue(rx_queue);
++
++ efx_for_each_channel(channel, efx)
++ efx_fini_debugfs_channel(channel);
++}
++
++/**
++ * efx_init_debugfs_nic - create debugfs directory for NIC
++ * @efx: Efx NIC
++ *
++ * Create debugfs directory containing parameter-files for @efx,
++ * and a subdirectory "errors" containing per-NIC error counts.
++ * Return a negative error code or 0 on success. The directories
++ * must be cleaned up using efx_fini_debugfs_nic().
++ */
++int efx_init_debugfs_nic(struct efx_nic *efx)
++{
++ int rc;
++
++ /* Create directory */
++ efx->debug_dir = debugfs_create_dir(pci_name(efx->pci_dev),
++ efx_debug_cards);
++ if (!efx->debug_dir)
++ goto err_mem;
++
++ /* Create errors directory */
++ efx->errors.debug_dir = debugfs_create_dir("errors", efx->debug_dir);
++ if (!efx->errors.debug_dir)
++ goto err_mem;
++
++ /* Create files */
++ rc = efx_init_debugfs_files(efx->debug_dir,
++ efx_debugfs_nic_parameters, (void *)efx);
++ if (rc)
++ goto err;
++ rc = efx_init_debugfs_files(efx->errors.debug_dir,
++ efx_debugfs_nic_error_parameters,
++ (void *)&efx->errors);
++ if (rc)
++ goto err;
++
++ return 0;
++
++ err_mem:
++ rc = -ENOMEM;
++ err:
++ efx_fini_debugfs_nic(efx);
++ return rc;
++}
++
++/**
++ * efx_fini_debugfs_nic - remove debugfs directories for NIC
++ * @efx: Efx NIC
++ *
++ * Remove debugfs directories created for @efx by efx_init_debugfs_nic().
++ */
++void efx_fini_debugfs_nic(struct efx_nic *efx)
++{
++ efx_fini_debugfs_dir(efx->errors.debug_dir,
++ efx_debugfs_nic_error_parameters, NULL);
++ efx->errors.debug_dir = NULL;
++ efx_fini_debugfs_dir(efx->debug_dir, efx_debugfs_nic_parameters, NULL);
++ efx->debug_dir = NULL;
++}
++
++/**
++ * efx_init_debugfs - create debugfs directories for sfc driver
++ *
++ * Create debugfs directories "sfc" and "sfc/cards". This must be
++ * called before any of the other functions that create debugfs
++ * directories. Return a negative error code or 0 on success. The
++ * directories must be cleaned up using efx_fini_debugfs().
++ */
++int efx_init_debugfs(void)
++{
++ /* Create top-level directory */
++#if defined(EFX_USE_DEBUGFS)
++ efx_debug_root = debugfs_create_dir("sfc", NULL);
++#else
++ efx_debug_root = proc_mkdir("sfc", proc_root_driver);
++#endif
++ if (!efx_debug_root)
++ goto err;
++
++ /* Create "cards" directory */
++ efx_debug_cards = debugfs_create_dir("cards", efx_debug_root);
++ if (!efx_debug_cards)
++ goto err;
++
++#if defined(EFX_USE_DEBUGFS)
++ /* Create compatibility sym-link */
++ if (!proc_symlink("sfc", proc_root_driver, "/sys/kernel/debug/sfc"))
++ goto err;
++#endif
++ return 0;
++
++ err:
++ efx_fini_debugfs();
++ return -ENOMEM;
++}
++
++/**
++ * efx_fini_debugfs - remove debugfs directories for sfc driver
++ *
++ * Remove directories created by efx_init_debugfs().
++ */
++void efx_fini_debugfs(void)
++{
++#if defined(EFX_USE_DEBUGFS)
++ remove_proc_entry("sfc", proc_root_driver);
++#endif
++ debugfs_remove(efx_debug_cards);
++ efx_debug_cards = NULL;
++ debugfs_remove(efx_debug_root);
++ efx_debug_root = NULL;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/debugfs.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/debugfs.h
+--- linux-2.6.18.8/drivers/net/sfc/debugfs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/debugfs.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,172 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_DEBUGFS_H
++#define EFX_DEBUGFS_H
++
++#ifdef CONFIG_SFC_DEBUGFS
++
++struct seq_file;
++
++struct efx_debugfs_parameter {
++ const char *name;
++ size_t offset;
++ int (*reader)(struct seq_file *, void *);
++};
++
++extern void efx_fini_debugfs_child(struct dentry *dir, const char *name);
++extern int efx_init_debugfs_netdev(struct net_device *net_dev);
++extern void efx_fini_debugfs_netdev(struct net_device *net_dev);
++extern int efx_init_debugfs_port(struct efx_nic *efx);
++extern void efx_fini_debugfs_port(struct efx_nic *efx);
++extern int efx_init_debugfs_nic(struct efx_nic *efx);
++extern void efx_fini_debugfs_nic(struct efx_nic *efx);
++extern int efx_init_debugfs_channels(struct efx_nic *efx);
++extern void efx_fini_debugfs_channels(struct efx_nic *efx);
++extern int efx_init_debugfs(void);
++extern void efx_fini_debugfs(void);
++extern int efx_extend_debugfs_port(struct efx_nic *efx,
++ void *context,
++ struct efx_debugfs_parameter *params);
++extern void efx_trim_debugfs_port(struct efx_nic *efx,
++ struct efx_debugfs_parameter *params);
++
++/* Helpers for handling debugfs entry reads */
++extern int efx_debugfs_read_uint(struct seq_file *, void *);
++extern int efx_debugfs_read_string(struct seq_file *, void *);
++extern int efx_debugfs_read_int(struct seq_file *, void *);
++extern int efx_debugfs_read_atomic(struct seq_file *, void *);
++extern int efx_debugfs_read_dword(struct seq_file *, void *);
++
++/* Handy macros for filling out parameters */
++
++/* Initialiser for a struct efx_debugfs_parameter with type-checking */
++#define EFX_PARAMETER(container_type, parameter, field_type, \
++ reader_function) { \
++ .name = #parameter, \
++ .offset = ((((field_type *) 0) == \
++ &((container_type *) 0)->parameter) ? \
++ offsetof(container_type, parameter) : \
++ offsetof(container_type, parameter)), \
++ .reader = reader_function, \
++}
++
++/* Likewise, but the file name is not taken from the field name */
++#define EFX_NAMED_PARAMETER(_name, container_type, parameter, field_type, \
++ reader_function) { \
++ .name = #_name, \
++ .offset = ((((field_type *) 0) == \
++ &((container_type *) 0)->parameter) ? \
++ offsetof(container_type, parameter) : \
++ offsetof(container_type, parameter)), \
++ .reader = reader_function, \
++}
++
++/* Likewise, but with one file for each of 4 lanes */
++#define EFX_PER_LANE_PARAMETER(prefix, suffix, container_type, parameter, \
++ field_type, reader_function) { \
++ .name = prefix "0" suffix, \
++ .offset = ((((field_type *) 0) == \
++ ((container_type *) 0)->parameter) ? \
++ offsetof(container_type, parameter[0]) : \
++ offsetof(container_type, parameter[0])), \
++ .reader = reader_function, \
++}, { \
++ .name = prefix "1" suffix, \
++ .offset = offsetof(container_type, parameter[1]), \
++ .reader = reader_function, \
++}, { \
++ .name = prefix "2" suffix, \
++ .offset = offsetof(container_type, parameter[2]), \
++ .reader = reader_function, \
++}, { \
++ .name = prefix "3" suffix, \
++ .offset = offsetof(container_type, parameter[3]), \
++ .reader = reader_function, \
++}
++
++/* A string parameter (string embedded in the structure) */
++#define EFX_STRING_PARAMETER(container_type, parameter) { \
++ .name = #parameter, \
++ .offset = ((((char *) 0) == \
++ ((container_type *) 0)->parameter) ? \
++ offsetof(container_type, parameter) : \
++ offsetof(container_type, parameter)), \
++ .reader = efx_debugfs_read_string, \
++}
++
++/* An unsigned integer parameter */
++#define EFX_UINT_PARAMETER(container_type, parameter) \
++ EFX_PARAMETER(container_type, parameter, \
++ unsigned int, efx_debugfs_read_uint)
++
++/* A dword parameter */
++#define EFX_DWORD_PARAMETER(container_type, parameter) \
++ EFX_PARAMETER(container_type, parameter, \
++ efx_dword_t, efx_debugfs_read_dword)
++
++/* An atomic_t parameter */
++#define EFX_ATOMIC_PARAMETER(container_type, parameter) \
++ EFX_PARAMETER(container_type, parameter, \
++ atomic_t, efx_debugfs_read_atomic)
++
++/* An integer parameter */
++#define EFX_INT_PARAMETER(container_type, parameter) \
++ EFX_PARAMETER(container_type, parameter, \
++ int, efx_debugfs_read_int)
++
++#else /* !CONFIG_SFC_DEBUGFS */
++
++static inline int efx_init_debugfs_netdev(struct net_device *net_dev)
++{
++ return 0;
++}
++static inline void efx_fini_debugfs_netdev(struct net_device *net_dev) {}
++static inline int efx_init_debugfs_port(struct efx_nic *efx)
++{
++ return 0;
++}
++static inline void efx_fini_debugfs_port(struct efx_nic *efx) {}
++static inline int efx_init_debugfs_nic(struct efx_nic *efx)
++{
++ return 0;
++}
++static inline void efx_fini_debugfs_nic(struct efx_nic *efx) {}
++static inline int efx_init_debugfs_channels(struct efx_nic *efx)
++{
++ return 0;
++}
++static inline void efx_fini_debugfs_channels(struct efx_nic *efx) {}
++static inline int efx_init_debugfs(void)
++{
++ return 0;
++}
++static inline void efx_fini_debugfs(void) {}
++
++#endif /* CONFIG_SFC_DEBUGFS */
++
++#endif /* EFX_DEBUGFS_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/driverlink_api.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/driverlink_api.h
+--- linux-2.6.18.8/drivers/net/sfc/driverlink_api.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/driverlink_api.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,612 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_DRIVERLINK_API_H
++#define EFX_DRIVERLINK_API_H
++
++#include <linux/list.h> /* for struct list_head */
++#if !defined(EFX_USE_FASTCALL)
++ #include <linux/version.h>
++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++ #define EFX_USE_FASTCALL yes
++ #include <linux/linkage.h>
++ #endif
++#endif
++
++/**
++ * DOC: Efx driverlink API
++ *
++ * This file must be included by any driver that wishes to attach to
++ * devices claimed by the Solarflare NIC driver (sfc). It allows separate
++ * kernel modules to expose other functionality offered by the NIC, with
++ * the sfc driver remaining in overall control.
++ *
++ * Overview:
++ *
++ * Driverlink clients define a &struct efx_dl_driver, and register
++ * this structure with the driverlink layer using
++ * efx_dl_register_driver(), which is exported by the sfc driver.
++ *
++ * The probe() routine of each driverlink client driver is called by
++ * the driverlink layer for each physical port in the system, after
++ * the sfc driver has performed start-of-day hardware initialisation
++ * and self-test. If ports are added or removed via pci hotplug then
++ * the &struct efx_dl_driver probe() or remove() routines are called
++ * as appropriate.
++ *
++ * If the port doesn't provide the necessary hardware resources for a
++ * client, then that client can return failure from its probe()
++ * routine. Information provided to the client driver at probe time
++ * includes
++ *
++ * Each probe() routine is given a unique &struct efx_dl_device per
++ * port, which means it can safely use the @priv member to store any
++ * useful state it needs. The probe routine also has the opportunity
++ * to provide a &struct efx_dl_callbacks via
++ * efx_dl_register_callbacks(), which allows the client to intercept
++ * the sfc driver's operations at strategic points.
++ *
++ * Occasionally, the underlying Efx device may need to be reset to
++ * recover from an error condition. The client's reset_suspend() and
++ * reset_resume() methods [if provided] will be called to enable the
++ * client to suspend operations and preserve any state before the
++ * reset. The client can itself request a reset using efx_dl_reset()
++ * or efx_dl_schedule_reset(), should it detect an error condition
++ * necessitating a reset.
++ *
++ * Example:
++ *
++ * The MTD driver (mtd.c) uses the driverlink layer.
++ */
++
++/* Forward declarations */
++struct pci_dev;
++struct net_device;
++struct sk_buff;
++struct efx_dl_device;
++struct efx_dl_device_info;
++
++/*
++ * This is used to guard against the registration of driverlink
++ * clients using an incorrect version of the API.
++ */
++#define EFX_DRIVERLINK_API_VERSION 1
++
++
++/**
++ * struct efx_dl_driver - An Efx driverlink device driver
++ *
++ * This is the analogue of a struct pci_driver for a normal PCI
++ * driver. Driverlink clients should register themselves using
++ * efx_dl_register_driver() at module initialisation, and deregister
++ * themselves using efx_dl_unregister_driver() at module exit.
++ *
++ * All calls to members of efx_dl_driver are serialised by a single
++ * semaphore, so you are allowed to sleep in these functions. Take care
++ * to not call driverlink methods from within these callbacks, otherwise
++ * a deadlock is possible.
++ *
++ * @name: Name of the driver
++ * @probe: Called when device added
++ * @remove: Called when device removed
++ * @reset_suspend: Called before device is reset
++ * @reset_resume: Called after device is reset
++ */
++struct efx_dl_driver {
++ const char *name;
++
++ /*
++ * probe - Handle device addition.
++ * @efx_dev: Efx driverlink device
++ * @net_dev: The net_dev relevant to this port
++ * @dev_info: A linked list of device information.
++ * @silicon_rev: Silicon revision name.
++ *
++ * This will be called after driverlink client registration for
++ * every port on the system, and for every port that appears
++ * thereafter via hotplug.
++ *
++ * The client may use either @efx_dev->pci_dev, the dev_info linked
++ * list of available driver information, or the silicon revision
++ * name to determine if they can support this port. If they can,
++ * they should return 0 to indicate the probe was successful. Any
++ * other return code indicates that the probe failed, and the
++ * @efx_dl_dev will be invalidated.
++ *
++ * The client should perform whatever initialisation it
++ * requires, and store a pointer to its private data in
++ * @efx_dl_dev->priv (which is not shared between clients).
++ * It may also wish to hook in a callbacks table using
++ * efx_dl_register_callbacks().
++ *
++ * Return a negative error code or 0 on success.
++ */
++ int (*probe) (struct efx_dl_device *efx_dl_dev,
++ const struct net_device *net_dev,
++ const struct efx_dl_device_info *dev_info,
++ const char *silicon_rev);
++
++ /*
++ * remove - Handle device removal.
++ * @efx_dev: Efx driverlink device
++ *
++ * This will be called at driver exit (or hotplug removal) for
++ * each registered driverlink client.
++ *
++ * The client must ensure that it has finished all operations
++ * using this device before returning from this method. If it
++ * has hooked in a callbacks table using
++ * efx_dl_register_callbacks(), it must unhook it using
++ * efx_dl_unregister_callbacks(), and then ensure that all
++ * callback-triggered operations (e.g. scheduled tasklets)
++ * have completed before returning. (It does not need to
++ * explicitly wait for callback methods to finish executing,
++ * since efx_dl_unregister_callbacks() will sleep until all
++ * callbacks have returned anyway.)
++ *
++ * Note that the device itself may not have been removed; it
++ * may be simply that the client is being unloaded
++ * via efx_dl_unregister_driver(). In this case other clients
++ * (and the sfc driver itself) will still be using the device,
++ * so the client cannot assume that the device itself is quiescent.
++ * In particular, callbacks may continue to be triggered at any
++ * point until efx_dl_unregister_callbacks() is called.
++ */
++ void (*remove) (struct efx_dl_device *efx_dev);
++
++ /*
++ * reset_suspend - Suspend ready for reset.
++ * @efx_dev: Efx driverlink device
++ *
++ * This method will be called immediately before a hardware
++ * reset (which may or may not have been initiated by the
++ * driverlink client). This client must save any state that it
++ * will need to restore after the reset, and suspend all
++ * operations that might access the hardware. It must not
++ * return until the client can guarantee to have stopped
++ * touching the hardware.
++ *
++ * It is guaranteed that callbacks will be inactive by the
++ * time this method is called; the driverlink layer will
++ * already have prevented new callbacks being made and waited
++ * for all callbacks functions to return before calling
++ * reset_suspend(). However, any delayed work scheduled by
++ * the callback functions (e.g. tasklets) may not yet have
++ * completed.
++ *
++ * This method is allowed to sleep, so waiting on tasklets,
++ * work queues etc. is permitted. There will always be a
++ * corresponding call to the reset_resume() method, so it is
++ * safe to e.g. down a semaphore within reset_suspend() and up
++ * it within reset_resume(). (However, you obviously cannot
++ * do the same with a spinlock).
++ *
++ * Note that the reset operation may be being carried out in
++ * the context of scheduled work, so you cannot use
++ * flush_scheduled_work() to ensure that any work you may have
++ * scheduled has completed.
++ *
++ * During hardware reset, there is a chance of receiving
++ * spurious interrupts, so the client's ISR (if any) should be
++ * unhooked or otherwise disabled.
++ */
++ void (*reset_suspend) (struct efx_dl_device *efx_dev);
++
++ /*
++ * reset_resume - Restore after a reset.
++ * @efx_dev: Efx driverlink device
++ * @ok: Reset success indicator
++ *
++ * This method will be called after a hardware reset. There
++ * will always have been a corresponding call to the
++ * reset_suspend() method beforehand.
++ *
++ * If @ok is non-zero, the client should restore the state
++ * that it saved during the call to reset_suspend() and resume
++ * normal operations.
++ *
++ * If @ok is zero, the reset operation has failed and the
++ * hardware is currently in an unusable state. In this case,
++ * the client should release any locks taken out by
++ * reset_suspend(), but should not take any other action; in
++ * particular, it must not access the hardware, nor resume
++ * normal operations. The hardware is effectively dead at
++ * this point, and our sole aim is to avoid deadlocking or
++ * crashing the host.
++ *
++ * The driverlink layer will still be locked when
++ * reset_resume() is called, so the client may not call
++ * driverlink functions. In particular, if the reset failed,
++ * the client must not call efx_dl_unregister_callbacks() at
++ * this point; it should wait until remove() is called.
++ */
++ void (*reset_resume) (struct efx_dl_device *efx_dev, int ok);
++
++/* private: */
++ struct list_head node;
++ struct list_head device_list;
++};
++
++/**
++ * DOC: Efx driverlink device information
++ *
++ * Each &struct efx_dl_device makes certain hardware resources visible
++ * to driverlink clients, and they describe which resources are
++ * available by passing a linked list of &struct efx_dl_device_info
++ * into the probe() routine.
++ *
++ * The driverlink client's probe function can iterate through the linked list,
++ * and provided that it understands the resources that are exported, it can
++ * choose to make use of them through an external interface.
++ */
++
++/**
++ * enum efx_dl_device_info_type - Device information identifier.
++ *
++ * Each distinct hardware resource API will have a member in this
++ * enumeration.
++ *
++ * @EFX_DL_FALCON_RESOURCES: Information type is &struct efx_dl_falcon_resources
++ */
++enum efx_dl_device_info_type {
++ /** Falcon resources available for export */
++ EFX_DL_FALCON_RESOURCES = 0,
++};
++
++/**
++ * struct efx_dl_device_info - device information structure
++ * @next: Link to next structure, if any
++ * @type: Type code for this structure
++ *
++ * This structure is embedded in other structures provided by the
++ * driverlink device provider, and implements a linked list of
++ * resources pertinent to a driverlink client.
++ *
++ * Example: &struct efx_dl_falcon_resources
++ */
++struct efx_dl_device_info {
++ struct efx_dl_device_info *next;
++ enum efx_dl_device_info_type type;
++};
++
++/**
++ * enum efx_dl_falcon_resource_flags - Falcon resource information flags.
++ *
++ * Flags that describe hardware variations for the described Falcon based port.
++ *
++ * @EFX_DL_FALCON_DUAL_FUNC: Port is dual-function.
++ * Certain silicon revisions have two pci functions, and require
++ * certain hardware resources to be accessed via the secondary
++ * function. See the discussion of @pci_dev in &struct efx_dl_device
++ * below.
++ * @EFX_DL_FALCON_USE_MSI: Port is initialised to use MSI/MSI-X interrupts.
++ * Falcon supports traditional legacy interrupts and MSI/MSI-X
++ * interrupts. Since the sfc driver supports either, as a run
++ * time configuration, driverlink drivers need to be aware of which
++ * one to use for their interrupting resources.
++ */
++enum efx_dl_falcon_resource_flags {
++ EFX_DL_FALCON_DUAL_FUNC = 0x1,
++ EFX_DL_FALCON_USE_MSI = 0x2,
++};
++
++/**
++ * struct efx_dl_falcon_resources - Falcon resource information.
++ *
++ * This structure describes Falcon hardware resources available for
++ * use by a driverlink driver.
++ *
++ * @hdr: Resource linked list header
++ * @biu_lock: Register access lock.
++ * Some Falcon revisions require register access for configuration
++ * registers to be serialised between ports and PCI functions.
++ * The sfc driver will provide the appropriate lock semantics for
++ * the underlying hardware.
++ * @buffer_table_min: First available buffer table entry
++ * @buffer_table_max: Last available buffer table entry + 1
++ * @evq_timer_min: First available event queue with timer
++ * @evq_timer_max: Last available event queue with timer + 1
++ * @evq_int_min: First available event queue with interrupt
++ * @evq_int_max: Last available event queue with interrupt + 1
++ * @rxq_min: First available RX queue
++ * @rxq_max: Last available RX queue + 1
++ * @txq_min: First available TX queue
++ * @txq_max: Last available TX queue + 1
++ * @flags: Hardware variation flags
++ */
++struct efx_dl_falcon_resources {
++ struct efx_dl_device_info hdr;
++ spinlock_t *biu_lock;
++ unsigned buffer_table_min, buffer_table_max;
++ unsigned evq_timer_min, evq_timer_max;
++ unsigned evq_int_min, evq_int_max;
++ unsigned rxq_min, rxq_max;
++ unsigned txq_min, txq_max;
++ enum efx_dl_falcon_resource_flags flags;
++};
++
++/**
++ * struct efx_dl_device - An Efx driverlink device.
++ *
++ * @pci_dev: Underlying PCI device.
++ * This is the PCI device used by the sfc driver. It will
++ * already have been enabled for bus-mastering DMA etc.
++ * @priv: Driver private data
++ * Driverlink clients can use this to store a pointer to their
++ * internal per-device data structure. Each (driver, device)
++ * tuple has a separate &struct efx_dl_device, so clients can use
++ * this @priv field independently.
++ * @driver: Efx driverlink driver for this device
++ */
++struct efx_dl_device {
++ struct pci_dev *pci_dev;
++ void *priv;
++ struct efx_dl_driver *driver;
++};
++
++/**
++ * enum efx_veto - Packet veto request flag.
++ *
++ * This is the return type for the rx_packet() and tx_packet() methods
++ * in &struct efx_dl_callbacks.
++ *
++ * @EFX_ALLOW_PACKET: Packet may be transmitted/received
++ * @EFX_VETO_PACKET: Packet must not be transmitted/received
++ */
++enum efx_veto {
++ EFX_ALLOW_PACKET = 0,
++ EFX_VETO_PACKET = 1,
++};
++
++/**
++ * struct efx_dl_callbacks - Efx callbacks
++ *
++ * These methods can be hooked in to the sfc driver via
++ * efx_dl_register_callbacks(). They allow clients to intercept and/or
++ * modify the behaviour of the sfc driver at predetermined points.
++ *
++ * For efficiency, only one client can hook each callback.
++ *
++ * Since these callbacks are called on packet transmit and reception
++ * paths, clients should avoid acquiring locks or allocating memory.
++ *
++ * @tx_packet: Called when packet is about to be transmitted
++ * @rx_packet: Called when packet is received
++ * @link_change: Called when link status has changed
++ * @request_mtu: Called to request MTU change
++ * @mtu_changed: Called when MTU has been changed
++ * @event: Called when NIC event is not handled by the sfc driver
++ */
++struct efx_dl_callbacks {
++ /*
++ * tx_packet - Packet about to be transmitted.
++ * @efx_dev: Efx driverlink device
++ * @skb: Socket buffer containing the packet to be sent
++ *
++ * This method is called for every packet about to be
++ * transmitted. It allows the client to snoop on traffic sent
++ * via the kernel queues.
++ *
++ * The method may return %EFX_VETO_PACKET in order to prevent
++ * the sfc driver from transmitting the packet. The net
++ * driver will then discard the packet. If the client wishes
++ * to retain a reference to the packet data after returning
++ * %EFX_VETO_PACKET, it must obtain its own copy of the
++ * packet (e.g. by calling skb_get(), or by copying out the
++ * packet data to an external buffer).
++ *
++ * This method must return quickly, since it will have a
++ * direct performance impact upon the sfc driver. It will be
++ * called with interrupts disabled (and may be called in
++ * interrupt context), so may not sleep. Since the sfc driver
++ * may have multiple TX queues, running in parallel, please avoid
++ * the need for locking if it all possible.
++ */
++#if defined(EFX_USE_FASTCALL)
++ enum efx_veto fastcall (*tx_packet) (struct efx_dl_device *efx_dev,
++ struct sk_buff *skb);
++#else
++ enum efx_veto (*tx_packet) (struct efx_dl_device *efx_dev,
++ struct sk_buff *skb);
++#endif
++
++ /*
++ * rx_packet - Packet received.
++ * @efx_dev: Efx driverlink device
++ * @pkt_hdr: Pointer to received packet
++ * @pkt_len: Length of received packet
++ *
++ * This method is called for every received packet. It allows
++ * the client to snoop on traffic received by the kernel
++ * queues.
++ *
++ * The method may return %EFX_VETO_PACKET in order to prevent
++ * the sfc driver from passing the packet to the kernel. The net
++ * driver will then discard the packet.
++ *
++ * This method must return quickly, since it will have a
++ * direct performance impact upon the sfc driver. It is
++ * called in tasklet context, so may not sleep. Note that
++ * there are per-channel tasklets in the sfc driver, so
++ * rx_packet() may be called simultaneously on different CPUs
++ * and must lock appropriately. The design of the sfc driver
++ * allows for lockless operation between receive channels, so
++ * please avoid the need for locking if at all possible.
++ */
++#if defined(EFX_USE_FASTCALL)
++ enum efx_veto fastcall (*rx_packet) (struct efx_dl_device *efx_dev,
++ const char *pkt_hdr, int pkt_len);
++#else
++ enum efx_veto (*rx_packet) (struct efx_dl_device *efx_dev,
++ const char *pkt_hdr, int pkt_len);
++#endif
++
++ /*
++ * link_change - Link status change.
++ * @efx_dev: Efx driverlink device
++ * @link_up: Link up indicator
++ *
++ * This method is called to inform the driverlink client
++ * whenever the PHY link status changes. By the time this
++ * function is called, the MAC has already been reconfigured
++ * with the new autonegotiation settings from the PHY.
++ *
++ * This method is called from tasklet context and may not
++ * sleep.
++ */
++ void (*link_change) (struct efx_dl_device *efx_dev, int link_up);
++
++ /*
++ * request_mtu: Request MTU change.
++ * @efx_dev: Efx driverlink device
++ * @new_mtu: Requested new MTU
++ *
++ * This method is called whenever the user requests an MTU
++ * change on an interface. The client may return an error, in
++ * which case the MTU change request will be denied. If the
++ * client returns success, the MAC will be reconfigured with a
++ * new maxmimum frame length equal to
++ * EFX_MAX_FRAME_LEN(new_mtu). The client will be notified
++ * via the mtu_changed() method once the MAC has been
++ * reconfigured.
++ *
++ * The current MTU for the port can be obtained via
++ * efx_dl_get_netdev(efx_dl_device)->mtu.
++ *
++ * The sfc driver guarantees that no other callback functions
++ * are in progress when this method is called. This function
++ * is called in process context and may sleep.
++ *
++ * Return a negative error code or 0 on success.
++ */
++ int (*request_mtu) (struct efx_dl_device *efx_dev, int new_mtu);
++
++ /*
++ * mtu_changed - MTU has been changed.
++ * @efx_dev: Efx driverlink device
++ * @mtu: The new MTU
++ *
++ * This method is called once the MAC has been reconfigured
++ * with a new MTU. There will have been a preceding call to
++ * request_mtu().
++ *
++ * The sfc driver guarantees that no other callback functions
++ * are in progress when this method is called. This function
++ * is called in process context and may sleep.
++ */
++ void (*mtu_changed) (struct efx_dl_device *efx_dev, int mtu);
++
++ /*
++ * event - Event callback.
++ * @efx_dev: Efx driverlink device
++ * @p_event: Pointer to event
++ *
++ * This method is called for each event that is not handled by the
++ * sfc driver.
++ */
++ void (*event) (struct efx_dl_device *efx_dev, void *p_event);
++};
++
++/* Include API version number in symbol used for efx_dl_register_driver */
++#define efx_dl_stringify_1(x, y) x ## y
++#define efx_dl_stringify_2(x, y) efx_dl_stringify_1(x, y)
++#define efx_dl_register_driver \
++ efx_dl_stringify_2(efx_dl_register_driver_api_ver_, \
++ EFX_DRIVERLINK_API_VERSION)
++
++extern int efx_dl_register_driver(struct efx_dl_driver *driver);
++
++extern void efx_dl_unregister_driver(struct efx_dl_driver *driver);
++
++extern int efx_dl_register_callbacks(struct efx_dl_device *efx_dev,
++ struct efx_dl_callbacks *callbacks);
++
++extern void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev,
++ struct efx_dl_callbacks *callbacks);
++
++extern void efx_dl_schedule_reset(struct efx_dl_device *efx_dev);
++
++/**
++ * efx_dl_for_each_device_info_matching - iterate an efx_dl_device_info list
++ * @_dev_info: Pointer to first &struct efx_dl_device_info
++ * @_type: Type code to look for
++ * @_info_type: Structure type corresponding to type code
++ * @_field: Name of &struct efx_dl_device_info field in the type
++ * @_p: Iterator variable
++ *
++ * Example:
++ *
++ * static int driver_dl_probe(... const struct efx_dl_device_info *dev_info ...)
++ * {
++ * struct efx_dl_falcon_resources *res;
++ *
++ * efx_dl_for_each_device_info_matching(dev_info,EFX_DL_FALCON_RESOURCES,
++ * struct efx_dl_falcon_resources,
++ * hdr, res) {
++ * if (res->flags & EFX_DL_FALCON_DUAL_FUNC) {
++ * .....
++ * }
++ * }
++ * }
++ */
++#define efx_dl_for_each_device_info_matching(_dev_info, _type, \
++ _info_type, _field, _p) \
++ for ((_p) = container_of((_dev_info), _info_type, _field); \
++ (_p) != NULL; \
++ (_p) = container_of((_p)->_field.next, _info_type, _field))\
++ if ((_p)->_field.type != _type) \
++ continue; \
++ else
++
++/**
++ * efx_dl_search_device_info - search an efx_dl_device_info list
++ * @_dev_info: Pointer to first &struct efx_dl_device_info
++ * @_type: Type code to look for
++ * @_info_type: Structure type corresponding to type code
++ * @_field: Name of &struct efx_dl_device_info member in this type
++ * @_p: Result variable
++ *
++ * Example:
++ *
++ * static int driver_dl_probe(... const struct efx_dl_device_info *dev_info ...)
++ * {
++ * struct efx_dl_falcon_resources *res;
++ *
++ * efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES,
++ * struct efx_dl_falcon_resources, hdr, res);
++ * if (res != NULL) {
++ * ....
++ * }
++ * }
++ */
++#define efx_dl_search_device_info(_dev_info, _type, _info_type, \
++ _field, _p) \
++ efx_dl_for_each_device_info_matching((_dev_info), (_type), \
++ _info_type, _field, (_p)) \
++ break;
++
++#endif /* EFX_DRIVERLINK_API_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/driverlink.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/driverlink.c
+--- linux-2.6.18.8/drivers/net/sfc/driverlink.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/driverlink.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,544 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005: Fen Systems Ltd.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/module.h>
++#include <linux/list.h>
++#include <linux/skbuff.h>
++#include <linux/rtnetlink.h>
++#include "net_driver.h"
++#include "efx.h"
++#include "driverlink.h"
++
++/* Driverlink semaphore
++ * This semaphore must be held for any operation that modifies any of
++ * the driverlink lists.
++ */
++static DEFINE_MUTEX(efx_driverlink_lock);
++
++/* List of all registered drivers */
++static LIST_HEAD(efx_driver_list);
++
++/* List of all registered Efx ports */
++static LIST_HEAD(efx_port_list);
++
++/* Driver link handle used internally to track devices */
++struct efx_dl_handle {
++ /* The efx_dl_device consumers see */
++ struct efx_dl_device efx_dev;
++ /* The efx_nic providers provide */
++ struct efx_nic *efx;
++ /* Per-device list */
++ struct list_head port_node;
++ /* Per-driver list */
++ struct list_head driver_node;
++};
++
++/* Get the handle for an efx_dl_device */
++static struct efx_dl_handle *efx_dl_handle(struct efx_dl_device *efx_dev)
++{
++ return container_of(efx_dev, struct efx_dl_handle, efx_dev);
++}
++
++/* Remove an Efx device
++ * You must hold the efx_driverlink_lock before calling this
++ * function.
++ */
++static void efx_dl_del_device(struct efx_dl_device *efx_dev)
++{
++ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
++
++ EFX_INFO(efx_handle->efx, "%s driverlink client unregistering\n",
++ efx_dev->driver->name);
++
++ /* Call driver's remove() routine */
++ if (efx_dev->driver->remove)
++ efx_dev->driver->remove(efx_dev);
++
++ /* Remove handle from per-driver and per-NIC lists */
++ list_del(&efx_handle->driver_node);
++ list_del(&efx_handle->port_node);
++
++ /* Free efx_handle structure */
++ kfree(efx_handle);
++}
++
++/* Try to add an Efx device
++ * Attempt to probe the given device with the driver, creating a
++ * new efx_dl_device. If the probe routine fails, because the driver
++ * doesn't support this port, then the efx_dl_device is destroyed,
++ */
++static void efx_dl_try_add_device(struct efx_nic *efx,
++ struct efx_dl_driver *driver)
++{
++ struct efx_dl_handle *efx_handle;
++ struct efx_dl_device *efx_dev;
++ int rc;
++
++ /* Allocate and initialise new efx_dl_device structure */
++ efx_handle = kzalloc(sizeof(*efx_handle), GFP_KERNEL);
++ efx_dev = &efx_handle->efx_dev;
++ efx_handle->efx = efx;
++ efx_dev->driver = driver;
++ efx_dev->pci_dev = efx->pci_dev;
++ INIT_LIST_HEAD(&efx_handle->port_node);
++ INIT_LIST_HEAD(&efx_handle->driver_node);
++
++ /* Attempt driver probe */
++ rc = driver->probe(efx_dev, efx->net_dev,
++ efx->dl_info, efx->silicon_rev);
++ if (rc)
++ goto fail;
++
++ /* Add device to per-driver and per-NIC lists */
++ list_add_tail(&efx_handle->driver_node, &driver->device_list);
++ list_add_tail(&efx_handle->port_node, &efx->dl_device_list);
++
++ EFX_INFO(efx, "%s driverlink client registered\n", driver->name);
++ return;
++
++ fail:
++ EFX_INFO(efx, "%s driverlink client skipped\n", driver->name);
++
++ kfree(efx_dev);
++}
++
++/**
++ * efx_dl_unregister_driver - unregister an Efx device driver
++ * @driver: Efx driverlink driver
++ *
++ * Unregisters an Efx driver. The driver's remove() method will be
++ * called for all Efx devices currently claimed by the driver.
++ */
++void efx_dl_unregister_driver(struct efx_dl_driver *driver)
++{
++ struct efx_dl_handle *efx_handle, *efx_handle_n;
++
++ printk(KERN_INFO "Efx driverlink unregistering %s driver\n",
++ driver->name);
++
++ /* Acquire lock. We can't return failure, so have to use
++ * down() instead of down_interruptible()
++ */
++ mutex_lock(&efx_driverlink_lock);
++
++ /* Remove all devices claimed by the driver */
++ list_for_each_entry_safe(efx_handle, efx_handle_n,
++ &driver->device_list, driver_node)
++ efx_dl_del_device(&efx_handle->efx_dev);
++
++ /* Remove driver from driver list */
++ list_del(&driver->node);
++
++ /* Release lock */
++ mutex_unlock(&efx_driverlink_lock);
++}
++EXPORT_SYMBOL(efx_dl_unregister_driver);
++
++/**
++ * efx_dl_register_driver - register an Efx device driver
++ * @driver: Efx driverlink driver
++ *
++ * Registers a new Efx driver. The driver's probe() method will be
++ * called for all Efx NICs currently registered.
++ *
++ * Return a negative error code or 0 on success.
++ */
++int efx_dl_register_driver(struct efx_dl_driver *driver)
++{
++ struct efx_nic *efx;
++ int rc;
++
++ printk(KERN_INFO "Efx driverlink registering %s driver\n",
++ driver->name);
++
++ /* Initialise driver list structures */
++ INIT_LIST_HEAD(&driver->node);
++ INIT_LIST_HEAD(&driver->device_list);
++
++ /* Acquire lock */
++ rc = mutex_lock_interruptible(&efx_driverlink_lock);
++ if (rc)
++ return rc;
++
++ /* Add driver to driver list */
++ list_add_tail(&driver->node, &efx_driver_list);
++
++ /* Feed all existing devices to driver */
++ list_for_each_entry(efx, &efx_port_list, dl_node)
++ efx_dl_try_add_device(efx, driver);
++
++ /* Release locks */
++ mutex_unlock(&efx_driverlink_lock);
++
++ return 0;
++}
++EXPORT_SYMBOL(efx_dl_register_driver);
++
++void efx_dl_unregister_nic(struct efx_nic *efx)
++{
++ struct efx_dl_handle *efx_handle, *efx_handle_n;
++
++ if (!efx)
++ return;
++
++ /* Acquire lock. We can't return failure, so have to use
++ * down() instead of down_interruptible()
++ */
++ mutex_lock(&efx_driverlink_lock);
++
++ /* Remove all devices related to this NIC */
++ list_for_each_entry_safe_reverse(efx_handle, efx_handle_n,
++ &efx->dl_device_list,
++ port_node)
++ efx_dl_del_device(&efx_handle->efx_dev);
++
++ /* Remove port from port list */
++ list_del(&efx->dl_node);
++
++ /* Release lock */
++ mutex_unlock(&efx_driverlink_lock);
++}
++
++int efx_dl_register_nic(struct efx_nic *efx)
++{
++ struct efx_dl_driver *driver;
++ int rc;
++
++ /* Acquire lock */
++ rc = mutex_lock_interruptible(&efx_driverlink_lock);
++ if (rc)
++ return rc;
++
++ /* Add port to port list */
++ list_add_tail(&efx->dl_node, &efx_port_list);
++
++ /* Feed port to all existing drivers */
++ list_for_each_entry(driver, &efx_driver_list, node)
++ efx_dl_try_add_device(efx, driver);
++
++ /* Release lock */
++ mutex_unlock(&efx_driverlink_lock);
++
++ return 0;
++}
++
++/*
++ * Dummy callback implementations.
++ *
++ * To avoid a branch point on the fast-path, the callbacks are always
++ * implemented - they are never NULL.
++ */
++#if defined(EFX_USE_FASTCALL)
++static enum efx_veto fastcall
++#else
++static enum efx_veto
++#endif
++efx_dummy_tx_packet_callback(struct efx_dl_device *efx_dev, struct sk_buff *skb)
++{
++ /* Never veto the packet */
++ return EFX_ALLOW_PACKET;
++}
++
++#if defined(EFX_USE_FASTCALL)
++static enum efx_veto fastcall
++#else
++static enum efx_veto
++#endif
++efx_dummy_rx_packet_callback(struct efx_dl_device *efx_dev,
++ const char *pkt_buf, int len)
++{
++ /* Never veto the packet */
++ return EFX_ALLOW_PACKET;
++}
++
++static void
++efx_dummy_link_change_callback(struct efx_dl_device *efx_dev, int link_up)
++{
++}
++
++static int
++efx_dummy_request_mtu_callback(struct efx_dl_device *efx_dev, int new_mtu)
++{
++ /* Always allow */
++ return 0;
++}
++
++static void
++efx_dummy_mtu_changed_callback(struct efx_dl_device *efx_dev, int mtu)
++{
++ return;
++}
++
++static void efx_dummy_event_callback(struct efx_dl_device *efx_dev, void *event)
++{
++ return;
++}
++
++struct efx_dl_callbacks efx_default_callbacks = {
++ .tx_packet = efx_dummy_tx_packet_callback,
++ .rx_packet = efx_dummy_rx_packet_callback,
++ .link_change = efx_dummy_link_change_callback,
++ .request_mtu = efx_dummy_request_mtu_callback,
++ .mtu_changed = efx_dummy_mtu_changed_callback,
++ .event = efx_dummy_event_callback,
++};
++
++#define EFX_DL_UNREGISTER_CALLBACK(_port, _dev, _member) \
++ do { \
++ BUG_ON((_port)->dl_cb_dev._member != (_dev)); \
++ (_port)->dl_cb._member = \
++ efx_default_callbacks._member; \
++ (_port)->dl_cb_dev._member = NULL; \
++ } while (0)
++
++
++#define EFX_DL_REGISTER_CALLBACK(_port, _dev, _from, _member) \
++ if ((_from)->_member) { \
++ BUG_ON((_port)->dl_cb_dev._member != NULL); \
++ (_port)->dl_cb._member = (_from)->_member; \
++ (_port)->dl_cb_dev._member = _dev; \
++ }
++
++/**
++ * efx_dl_unregister_callbacks - unregister callbacks for an Efx NIC
++ * @efx_dev: Efx driverlink device
++ * @callbacks: Callback list
++ *
++ * This removes a set of callbacks registered with
++ * efx_dl_register_callbacks(). It should be called as part of the
++ * client's remove() method.
++ *
++ * The net driver will ensure that all callback functions have
++ * returned to the net driver before efx_dl_unregister_callbacks()
++ * returns. Note that the device itself may still be running when the
++ * client's remove() method is called. The client must therefore
++ * unhook its callbacks using efx_dl_unregister_callbacks() and only
++ * then ensure that any delayed tasks triggered by callback methods
++ * (e.g. scheduled tasklets) have completed.
++ */
++void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev,
++ struct efx_dl_callbacks *callbacks)
++{
++ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
++ struct efx_nic *efx = efx_handle->efx;
++
++ /* Suspend net driver operations */
++ efx_suspend(efx);
++
++ EFX_INFO(efx, "removing callback hooks into %s driver\n",
++ efx_dev->driver->name);
++
++ if (callbacks->tx_packet)
++ EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, tx_packet);
++
++ if (callbacks->rx_packet)
++ EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, rx_packet);
++
++ if (callbacks->link_change)
++ EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, link_change);
++
++ if (callbacks->request_mtu)
++ EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, request_mtu);
++
++ if (callbacks->mtu_changed)
++ EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, mtu_changed);
++
++ if (callbacks->event)
++ EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, event);
++
++ /* Resume net driver operations */
++ efx_resume(efx);
++}
++EXPORT_SYMBOL(efx_dl_unregister_callbacks);
++
++/**
++ * efx_dl_register_callbacks - register callbacks for an Efx NIC
++ * @efx_dev: Efx driverlink device
++ * @callbacks: Callback list
++ *
++ * This registers a set of callback functions with the net driver.
++ * These functions will be called at various key points to allow
++ * external code to monitor and/or modify the behaviour of the network
++ * driver. Any of the callback function pointers may be %NULL if a
++ * callback is not required. The intended user of this mechanism is
++ * the SFC char driver.
++ *
++ * This client should call efx_dl_register_callbacks() during its
++ * probe() method. The client must ensure that it also calls
++ * efx_dl_unregister_callbacks() as part of its remove() method.
++ *
++ * Only one function may be registered for each callback per NIC.
++ * If a requested callback is already registered for this NIC, this
++ * function will return -%EBUSY.
++ *
++ * The device may already be running, so the client must be prepared
++ * for callbacks to be triggered immediately after calling
++ * efx_dl_register_callbacks().
++ *
++ * Return a negative error code or 0 on success.
++ */
++int efx_dl_register_callbacks(struct efx_dl_device *efx_dev,
++ struct efx_dl_callbacks *callbacks)
++{
++ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
++ struct efx_nic *efx = efx_handle->efx;
++ int rc = 0;
++
++ /* Suspend net driver operations */
++ efx_suspend(efx);
++
++ /* Check that the requested callbacks are not already hooked. */
++ if ((callbacks->tx_packet && efx->dl_cb_dev.tx_packet) ||
++ (callbacks->rx_packet && efx->dl_cb_dev.rx_packet) ||
++ (callbacks->link_change && efx->dl_cb_dev.link_change) ||
++ (callbacks->request_mtu && efx->dl_cb_dev.request_mtu) ||
++ (callbacks->mtu_changed && efx->dl_cb_dev.mtu_changed) ||
++ (callbacks->event && efx->dl_cb_dev.event)) {
++ rc = -EBUSY;
++ goto out;
++ }
++
++ EFX_INFO(efx, "adding callback hooks to %s driver\n",
++ efx_dev->driver->name);
++
++ /* Hook in callbacks. For maximum speed, we never check to
++ * see whether these are NULL before calling; therefore we
++ * must ensure that they are never NULL. If the set we're
++ * being asked to hook in is sparse, we leave the default
++ * values in place for the empty hooks.
++ */
++ EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, tx_packet);
++ EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, rx_packet);
++ EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, link_change);
++ EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, request_mtu);
++ EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, mtu_changed);
++ EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, event);
++
++ out:
++ /* Resume net driver operations */
++ efx_resume(efx);
++
++ return rc;
++}
++EXPORT_SYMBOL(efx_dl_register_callbacks);
++
++/**
++ * efx_dl_schedule_reset - schedule an Efx NIC reset
++ * @efx_dev: Efx driverlink device
++ *
++ * This schedules a hardware reset for a short time in the future. It
++ * can be called from any context, and so can be used when
++ * efx_dl_reset() cannot be called.
++ */
++void efx_dl_schedule_reset(struct efx_dl_device *efx_dev)
++{
++ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
++ struct efx_nic *efx = efx_handle->efx;
++
++ efx_schedule_reset(efx, RESET_TYPE_ALL);
++}
++EXPORT_SYMBOL(efx_dl_schedule_reset);
++
++/*
++ * Lock the driverlink layer before a reset
++ * To avoid deadlock, efx_driverlink_lock needs to be acquired before
++ * efx->suspend_lock.
++ */
++void efx_dl_reset_lock(void)
++{
++ /* Acquire lock */
++ mutex_lock(&efx_driverlink_lock);
++}
++
++/*
++ * Unlock the driverlink layer after a reset
++ * This call must be matched against efx_dl_reset_lock.
++ */
++void efx_dl_reset_unlock(void)
++{
++ /* Acquire lock */
++ mutex_unlock(&efx_driverlink_lock);
++}
++
++/*
++ * Suspend ready for reset
++ * This calls the reset_suspend method of all drivers registered to
++ * the specified NIC. It must only be called between
++ * efx_dl_reset_lock and efx_dl_reset_unlock.
++ */
++void efx_dl_reset_suspend(struct efx_nic *efx)
++{
++ struct efx_dl_handle *efx_handle;
++ struct efx_dl_device *efx_dev;
++
++ BUG_ON(!mutex_is_locked(&efx_driverlink_lock));
++
++ /* Call suspend method of each driver in turn */
++ list_for_each_entry_reverse(efx_handle,
++ &efx->dl_device_list,
++ port_node) {
++ efx_dev = &efx_handle->efx_dev;
++ if (efx_dev->driver->reset_suspend)
++ efx_dev->driver->reset_suspend(efx_dev);
++ }
++}
++
++/*
++ * Resume after a reset
++ * This calls the reset_resume method of all drivers registered to the
++ * specified NIC. It must only be called between efx_dl_reset_lock
++ * and efx_dl_reset_unlock.
++ */
++void efx_dl_reset_resume(struct efx_nic *efx, int ok)
++{
++ struct efx_dl_handle *efx_handle;
++ struct efx_dl_device *efx_dev;
++
++ BUG_ON(!mutex_is_locked(&efx_driverlink_lock));
++
++ /* Call resume method of each driver in turn */
++ list_for_each_entry(efx_handle, &efx->dl_device_list,
++ port_node) {
++ efx_dev = &efx_handle->efx_dev;
++ if (efx_dev->driver->reset_resume)
++ efx_dev->driver->reset_resume(efx_dev, ok);
++ }
++}
++
++/**
++ * efx_dl_get_nic - obtain the Efx NIC for the given driverlink device
++ * @efx_dev: Efx driverlink device
++ *
++ * Get a pointer to the &struct efx_nic corresponding to
++ * @efx_dev. This can be used by driverlink clients built along with
++ * the sfc driver, which may have intimate knowledge of its internals.
++ */
++struct efx_nic *efx_dl_get_nic(struct efx_dl_device *efx_dev)
++{
++ return efx_dl_handle(efx_dev)->efx;
++}
++EXPORT_SYMBOL(efx_dl_get_nic);
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/driverlink.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/driverlink.h
+--- linux-2.6.18.8/drivers/net/sfc/driverlink.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/driverlink.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,93 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005: Fen Systems Ltd.
++ * Copyright 2006: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_DRIVERLINK_H
++#define EFX_DRIVERLINK_H
++
++/* Forward declarations */
++struct efx_dl_device;
++struct efx_nic;
++
++/*
++ * Efx driverlink
++ *
++ * This header file defines the portions of the Efx driverlink
++ * interface that are used only within the sfc module. It also
++ * declares efx_dl_get_nic(), which may be used by sfc_mtd
++ * and any other module built along with sfc.
++ */
++
++
++/* Efx callback devices
++ *
++ * A list of the devices that own each callback. The partner to
++ * struct efx_dl_callbacks
++ */
++struct efx_dl_cb_devices {
++ /* Device owning the tx_packet callback */
++ struct efx_dl_device *tx_packet;
++ /* Device owning the rx_packet callback */
++ struct efx_dl_device *rx_packet;
++ /* Device owning the link_change callback. */
++ struct efx_dl_device *link_change;
++ /* Device owning the request_mtu callback. */
++ struct efx_dl_device *request_mtu;
++ /* Device owning the mtu_changed callback. */
++ struct efx_dl_device *mtu_changed;
++ /* Device owning the event callback. */
++ struct efx_dl_device *event;
++};
++
++/* No-op callbacks used for initialisation */
++extern struct efx_dl_callbacks efx_default_callbacks;
++
++/* Macro used to invoke callbacks */
++#define EFX_DL_CALLBACK(_port, _name, ...) \
++ (_port)->dl_cb._name((_port)->dl_cb_dev._name, __VA_ARGS__)
++
++/* Register an Efx NIC */
++extern int efx_dl_register_nic(struct efx_nic *efx);
++
++/* Unregister an Efx NIC */
++extern void efx_dl_unregister_nic(struct efx_nic *efx);
++
++/* Lock the driverlink layer prior to a reset */
++extern void efx_dl_reset_lock(void);
++
++/* Unlock the driverlink layer following a reset */
++extern void efx_dl_reset_unlock(void);
++
++/* Suspend all drivers prior to a hardware reset */
++extern void efx_dl_reset_suspend(struct efx_nic *efx);
++
++/* Resume all drivers after a hardware reset */
++extern void efx_dl_reset_resume(struct efx_nic *efx, int ok);
++
++/* Obtain the Efx NIC for the given driverlink device. */
++extern struct efx_nic *efx_dl_get_nic(struct efx_dl_device *efx_dev);
++
++#endif /* EFX_DRIVERLINK_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/efx.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/efx.c
+--- linux-2.6.18.8/drivers/net/sfc/efx.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/efx.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2783 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/notifier.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/in.h>
++#include <linux/crc32.h>
++#include <linux/ethtool.h>
++#include <asm/uaccess.h>
++#include "net_driver.h"
++#include "gmii.h"
++#include "driverlink.h"
++#include "selftest.h"
++#include "debugfs.h"
++#include "ethtool.h"
++#include "tx.h"
++#include "rx.h"
++#include "efx.h"
++#include "mdio_10g.h"
++#include "falcon.h"
++#include "workarounds.h"
++
++/**************************************************************************
++ *
++ * Type name strings
++ *
++ **************************************************************************
++ */
++
++/* Loopback mode names (see LOOPBACK_MODE()) */
++const unsigned int efx_loopback_mode_max = LOOPBACK_MAX;
++const char *efx_loopback_mode_names[] = {
++ [LOOPBACK_NONE] = "NONE",
++ [LOOPBACK_MAC] = "MAC",
++ [LOOPBACK_XGMII] = "XGMII",
++ [LOOPBACK_XGXS] = "XGXS",
++ [LOOPBACK_XAUI] = "XAUI",
++ [LOOPBACK_PHY] = "PHY",
++ [LOOPBACK_PHYXS] = "PHY(XS)",
++ [LOOPBACK_PCS] = "PHY(PCS)",
++ [LOOPBACK_PMAPMD] = "PHY(PMAPMD)",
++ [LOOPBACK_NETWORK] = "NETWORK",
++};
++
++/* Interrupt mode names (see INT_MODE())) */
++const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
++const char *efx_interrupt_mode_names[] = {
++ [EFX_INT_MODE_MSIX] = "MSI-X",
++ [EFX_INT_MODE_MSI] = "MSI",
++ [EFX_INT_MODE_LEGACY] = "legacy",
++};
++
++/* PHY type names (see PHY_TYPE())) */
++const unsigned int efx_phy_type_max = PHY_TYPE_MAX;
++const char *efx_phy_type_names[] = {
++ [PHY_TYPE_NONE] = "none",
++ [PHY_TYPE_CX4_RTMR] = "Mysticom CX4",
++ [PHY_TYPE_1G_ALASKA] = "1G Alaska",
++ [PHY_TYPE_10XPRESS] = "SFC 10Xpress",
++ [PHY_TYPE_XFP] = "Quake XFP",
++ [PHY_TYPE_PM8358] = "PM8358 XAUI",
++};
++
++const unsigned int efx_reset_type_max = RESET_TYPE_MAX;
++const char *efx_reset_type_names[] = {
++ [RESET_TYPE_INVISIBLE] = "INVISIBLE",
++ [RESET_TYPE_ALL] = "ALL",
++ [RESET_TYPE_WORLD] = "WORLD",
++ [RESET_TYPE_DISABLE] = "DISABLE",
++ [RESET_TYPE_MONITOR] = "MONITOR",
++ [RESET_TYPE_INT_ERROR] = "INT_ERROR",
++ [RESET_TYPE_RX_RECOVERY] = "RX_RECOVERY",
++};
++
++const unsigned int efx_nic_state_max = STATE_MAX;
++const char *efx_nic_state_names[] = {
++ [STATE_INIT] = "INIT",
++ [STATE_RUNNING] = "RUNNING",
++ [STATE_FINI] = "FINI",
++ [STATE_RESETTING] = "RESETTING",
++ [STATE_DISABLED] = "DISABLED",
++};
++
++#define EFX_MAX_MTU (9 * 1024)
++
++
++/**************************************************************************
++ *
++ * Configurable values
++ *
++ *************************************************************************/
++
++/*
++ * Use separate channels for TX and RX events
++ *
++ * Set this to 1 to use separate channels for TX and RX. It allows us to
++ * apply a higher level of interrupt moderation to TX events.
++ *
++ * This is forced to 0 for MSI interrupt mode as the interrupt vector
++ * is not written
++ */
++static unsigned int separate_tx_and_rx_channels = 1;
++
++/* This is the weight assigned to each of the (per-channel) virtual
++ * NAPI devices.
++ */
++static int napi_weight = 64;
++
++/* This is the time (in jiffies) between invocations of the hardware
++ * monitor, which checks for known hardware bugs and resets the
++ * hardware and driver as necessary.
++ */
++unsigned int efx_monitor_interval = 1 * HZ;
++
++/* This controls whether or not the hardware monitor will trigger a
++ * reset when it detects an error condition.
++ */
++static unsigned int monitor_reset = 1;
++
++/* This controls whether or not the driver will initialise devices
++ * with invalid MAC addresses stored in the EEPROM or flash. If true,
++ * such devices will be initialised with a random locally-generated
++ * MAC address. This allows for loading the efx_mtd driver to
++ * reprogram the flash, even if the flash contents (including the MAC
++ * address) have previously been erased.
++ */
++static unsigned int allow_bad_hwaddr;
++
++/* Initial interrupt moderation settings. They can be modified after
++ * module load with ethtool.
++ *
++ * The default for RX should strike a balance between increasing the
++ * round-trip latency and reducing overhead.
++ */
++static unsigned int rx_irq_mod_usec = 60;
++
++/* Initial interrupt moderation settings. They can be modified after
++ * module load with ethtool.
++ *
++ * This default is chosen to ensure that a 10G link does not go idle
++ * while a TX queue is stopped after it has become full. A queue is
++ * restarted when it drops below half full. The time this takes (assuming
++ * worst case 3 descriptors per packet and 1024 descriptors) is
++ * 512 / 3 * 1.2 = 205 usec.
++ */
++static unsigned int tx_irq_mod_usec = 150;
++
++/* Ignore online self-test failures at load
++ *
++ * If set to 1, then the driver will not fail to load
++ * if the online self-test fails. Useful only during testing
++ */
++static unsigned int allow_load_on_failure;
++
++/* Set to 1 to enable the use of Message-Signalled Interrupts (MSI).
++ * MSI will not work on some motherboards due to limitations of the
++ * chipset, so the default is off.
++ *
++ * This is the highest capability interrupt mode to use
++ * 0 => MSI-X
++ * 1 => MSI
++ * 2 => legacy
++ */
++static unsigned int interrupt_mode;
++
++/* If set to 1, then the driver will perform an offline self test
++ * when each interface first comes up. This will appear like the
++ * interface bounces up and down
++ */
++static unsigned int onload_offline_selftest = 1;
++
++/* This is the requested number of CPUs to use for Receive-Side Scaling (RSS),
++ * i.e. the number of CPUs among which we may distribute simultaneous
++ * interrupt handling.
++ *
++ * Cards without MSI-X will only target one CPU
++ *
++ * Default (0) means to use all CPUs in the system. This parameter
++ * can be set using "rss_cpus=xxx" when loading the module.
++ */
++static unsigned int rss_cpus;
++module_param(rss_cpus, uint, 0444);
++MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
++
++/**************************************************************************
++ *
++ * Utility functions and prototypes
++ *
++ *************************************************************************/
++static void efx_remove_channel(struct efx_channel *channel);
++static void efx_remove_port(struct efx_nic *efx);
++static void efx_fini_napi(struct efx_nic *efx);
++static void efx_fini_channels(struct efx_nic *efx);
++
++/**************************************************************************
++ *
++ * Event queue processing
++ *
++ *************************************************************************/
++
++/* Process channel's event queue
++ *
++ * This function is responsible for processing the event queue of a
++ * single channel. The caller must guarantee that this function will
++ * never be concurrently called more than once on the same channel,
++ * though different channels may be being processed concurrently.
++ */
++static inline int efx_process_channel(struct efx_channel *channel, int rx_quota)
++{
++ int rxdmaqs;
++ struct efx_rx_queue *rx_queue;
++
++ if (unlikely(channel->efx->reset_pending != RESET_TYPE_NONE ||
++ !channel->enabled))
++ return rx_quota;
++
++ rxdmaqs = falcon_process_eventq(channel, &rx_quota);
++
++ /* Deliver last RX packet. */
++ if (channel->rx_pkt) {
++ __efx_rx_packet(channel, channel->rx_pkt,
++ channel->rx_pkt_csummed);
++ channel->rx_pkt = NULL;
++ }
++
++ efx_rx_strategy(channel);
++
++ /* Refill descriptor rings as necessary */
++ rx_queue = &channel->efx->rx_queue[0];
++ while (rxdmaqs) {
++ if (rxdmaqs & 0x01)
++ efx_fast_push_rx_descriptors(rx_queue);
++ rx_queue++;
++ rxdmaqs >>= 1;
++ }
++
++ return rx_quota;
++}
++
++/* Mark channel as finished processing
++ *
++ * Note that since we will not receive further interrupts for this
++ * channel before we finish processing and call the eventq_read_ack()
++ * method, there is no need to use the interrupt hold-off timers.
++ */
++static inline void efx_channel_processed(struct efx_channel *channel)
++{
++ /* Write to EVQ_RPTR_REG. If a new event arrived in a race
++ * with finishing processing, a new interrupt will be raised.
++ */
++ channel->work_pending = 0;
++ smp_wmb(); /* Ensure channel updated before any new interrupt. */
++ falcon_eventq_read_ack(channel);
++}
++
++/* NAPI poll handler
++ *
++ * NAPI guarantees serialisation of polls of the same device, which
++ * provides the guarantee required by efx_process_channel().
++ */
++#if !defined(EFX_HAVE_OLD_NAPI)
++static int efx_poll(struct napi_struct *napi, int budget)
++{
++ struct efx_channel *channel =
++ container_of(napi, struct efx_channel, napi_str);
++ struct net_device *napi_dev = channel->napi_dev;
++#else
++static int efx_poll(struct net_device *napi, int *budget_ret)
++{
++ struct net_device *napi_dev = napi;
++ struct efx_channel *channel = napi_dev->priv;
++ int budget = min(napi_dev->quota, *budget_ret);
++#endif
++ int unused;
++ int rx_packets;
++
++ EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
++ channel->channel, raw_smp_processor_id());
++
++ unused = efx_process_channel(channel, budget);
++ rx_packets = (budget - unused);
++#if defined(EFX_HAVE_OLD_NAPI)
++ napi_dev->quota -= rx_packets;
++ *budget_ret -= rx_packets;
++#endif
++
++ if (rx_packets < budget) {
++ /* There is no race here; although napi_disable() will
++ * only wait for netif_rx_complete(), this isn't a problem
++ * since efx_channel_processed() will have no effect if
++ * interrupts have already been disabled.
++ */
++ netif_rx_complete(napi_dev, napi);
++ efx_channel_processed(channel);
++ }
++
++#if !defined(EFX_HAVE_OLD_NAPI)
++ return rx_packets;
++#else
++ return (rx_packets >= budget);
++#endif
++}
++
++/* Process the eventq of the specified channel immediately on this CPU
++ *
++ * Disable hardware generated interrupts, wait for any existing
++ * processing to finish, then directly poll (and ack ) the eventq.
++ * Finally reenable NAPI and interrupts.
++ *
++ * Since we are touching interrupts the caller should hold the suspend lock
++ */
++void efx_process_channel_now(struct efx_channel *channel)
++{
++ struct efx_nic *efx = channel->efx;
++
++ BUG_ON(!channel->used_flags);
++ BUG_ON(!channel->enabled);
++
++ /* Disable interrupts and wait for ISRs to complete */
++ falcon_disable_interrupts(efx);
++ if (efx->legacy_irq)
++ synchronize_irq(efx->legacy_irq);
++ if (channel->has_interrupt && channel->irq)
++ synchronize_irq(channel->irq);
++
++ /* Wait for any NAPI processing to complete */
++ napi_disable(&channel->napi_str);
++
++ /* Poll the channel */
++ (void) efx_process_channel(channel, efx->type->evq_size);
++
++ /* Ack the eventq. This may cause an interrupt to be generated
++ * when they are reenabled */
++ efx_channel_processed(channel);
++
++ /* Reenable NAPI polling */
++ napi_enable(&channel->napi_str);
++
++ /* Reenable interrupts */
++ falcon_enable_interrupts(efx);
++}
++
++/* Create event queue
++ * Event queue memory allocations are done only once. If the channel
++ * is reset, the memory buffer will be reused; this guards against
++ * errors during channel reset and also simplifies interrupt handling.
++ */
++static int efx_probe_eventq(struct efx_channel *channel)
++{
++ EFX_LOG(channel->efx, "chan %d create event queue\n", channel->channel);
++
++ return falcon_probe_eventq(channel);
++}
++
++/* Prepare channel's event queue */
++static int efx_init_eventq(struct efx_channel *channel)
++{
++ EFX_LOG(channel->efx, "chan %d init event queue\n", channel->channel);
++
++ ASSERT_RTNL();
++
++ /* Initialise fields */
++ channel->eventq_read_ptr = 0;
++
++ return falcon_init_eventq(channel);
++}
++
++static void efx_fini_eventq(struct efx_channel *channel)
++{
++ EFX_LOG(channel->efx, "chan %d fini event queue\n", channel->channel);
++
++ ASSERT_RTNL();
++
++ falcon_fini_eventq(channel);
++}
++
++static void efx_remove_eventq(struct efx_channel *channel)
++{
++ EFX_LOG(channel->efx, "chan %d remove event queue\n", channel->channel);
++
++ falcon_remove_eventq(channel);
++}
++
++/**************************************************************************
++ *
++ * Channel handling
++ *
++ *************************************************************************/
++
++/* Setup per-NIC RX buffer parameters.
++ * Calculate the rx buffer allocation parameters required to support
++ * the current MTU, including padding for header alignment and overruns.
++ */
++static void efx_calc_rx_buffer_params(struct efx_nic *efx)
++{
++ unsigned int order, len;
++
++ len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
++ EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
++ efx->type->rx_buffer_padding);
++
++ /* Page-based allocation page-order */
++ for (order = 0; ((1u << order) * PAGE_SIZE) < len; ++order)
++ ;
++
++ efx->rx_buffer_len = len;
++ efx->rx_buffer_order = order;
++}
++
++static int efx_probe_channel(struct efx_channel *channel)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ int rc;
++
++ EFX_LOG(channel->efx, "creating channel %d\n", channel->channel);
++
++ rc = efx_probe_eventq(channel);
++ if (rc)
++ goto fail1;
++
++ efx_for_each_channel_tx_queue(tx_queue, channel) {
++ rc = efx_probe_tx_queue(tx_queue);
++ if (rc)
++ goto fail2;
++ }
++
++ efx_for_each_channel_rx_queue(rx_queue, channel) {
++ rc = efx_probe_rx_queue(rx_queue);
++ if (rc)
++ goto fail3;
++ }
++
++ channel->n_rx_frm_trunc = 0;
++
++ return 0;
++
++ fail3:
++ efx_for_each_channel_rx_queue(rx_queue, channel)
++ efx_remove_rx_queue(rx_queue);
++ fail2:
++ efx_for_each_channel_tx_queue(tx_queue, channel)
++ efx_remove_tx_queue(tx_queue);
++ fail1:
++ return rc;
++}
++
++
++/* Channels are shutdown and reinitialised whilst the NIC is running
++ * to propagate configuration changes (mtu, checksum offload), or
++ * to clear hardware error conditions
++ */
++static int efx_init_channels(struct efx_nic *efx)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ struct efx_channel *channel;
++ int rc = 0;
++
++ /* Recalculate the rx buffer parameters */
++ efx_calc_rx_buffer_params(efx);
++
++ /* Initialise the channels */
++ efx_for_each_channel(channel, efx) {
++ EFX_LOG(channel->efx, "init chan %d\n", channel->channel);
++
++ rc = efx_init_eventq(channel);
++ if (rc)
++ goto err;
++
++ efx_for_each_channel_tx_queue(tx_queue, channel) {
++ rc = efx_init_tx_queue(tx_queue);
++ if (rc)
++ goto err;
++ }
++
++ /* The rx buffer allocation strategy is MTU dependent */
++ efx_rx_strategy(channel);
++
++ efx_for_each_channel_rx_queue(rx_queue, channel) {
++ rc = efx_init_rx_queue(rx_queue);
++ if (rc)
++ goto err;
++ }
++
++ WARN_ON(channel->rx_pkt != NULL);
++ efx_rx_strategy(channel);
++ }
++
++ return 0;
++
++ err:
++ EFX_ERR(efx, "failed to initialise channel %d\n",
++ channel ? channel->channel : -1);
++ efx_fini_channels(efx);
++ return rc;
++}
++
++/* This enables event queue processing and packet transmission.
++ *
++ * Note that this function is not allowed to fail, since that would
++ * introduce too much complexity into the suspend/resume path.
++ */
++static void efx_start_channel(struct efx_channel *channel)
++{
++ struct efx_rx_queue *rx_queue;
++
++ EFX_LOG(channel->efx, "starting chan %d\n", channel->channel);
++
++ if (!(channel->efx->net_dev->flags & IFF_UP))
++ netif_napi_add(channel->napi_dev, &channel->napi_str,
++ efx_poll, napi_weight);
++
++ /* Mark channel as enabled */
++ channel->work_pending = 0;
++ channel->enabled = 1;
++ smp_wmb(); /* ensure channel updated before first interrupt */
++
++ /* Enable NAPI poll handler */
++ napi_enable(&channel->napi_str);
++
++ /* Load up RX descriptors */
++ efx_for_each_channel_rx_queue(rx_queue, channel)
++ efx_fast_push_rx_descriptors(rx_queue);
++}
++
++/* This disables event queue processing and packet transmission.
++ * This function does not guarantee that all queue processing
++ * (e.g. RX refill) is complete.
++ */
++static void efx_stop_channel(struct efx_channel *channel)
++{
++ struct efx_rx_queue *rx_queue;
++
++ if (!channel->enabled)
++ return;
++
++ EFX_LOG(channel->efx, "stop chan %d\n", channel->channel);
++
++ /* Mark channel as disabled */
++ channel->enabled = 0;
++
++ /* Wait for any NAPI processing to complete */
++ napi_disable(&channel->napi_str);
++
++ /* Ensure that any worker threads have exited or will be
++ * no-ops.
++ */
++ efx_for_each_channel_rx_queue(rx_queue, channel) {
++ spin_lock_bh(&rx_queue->add_lock);
++ spin_unlock_bh(&rx_queue->add_lock);
++ }
++}
++
++static void efx_fini_channels(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++
++ ASSERT_RTNL();
++
++ efx_for_each_channel(channel, efx) {
++ EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel);
++
++ efx_for_each_channel_rx_queue(rx_queue, channel)
++ efx_fini_rx_queue(rx_queue);
++ efx_for_each_channel_tx_queue(tx_queue, channel)
++ efx_fini_tx_queue(tx_queue);
++ }
++
++ /* Do the event queues last so that we can handle flush events
++ * for all DMA queues. */
++ efx_for_each_channel(channel, efx) {
++ EFX_LOG(channel->efx, "shut down evq %d\n", channel->channel);
++
++ efx_fini_eventq(channel);
++ }
++}
++
++static void efx_remove_channel(struct efx_channel *channel)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++
++ EFX_LOG(channel->efx, "destroy chan %d\n", channel->channel);
++
++ efx_for_each_channel_rx_queue(rx_queue, channel)
++ efx_remove_rx_queue(rx_queue);
++ efx_for_each_channel_tx_queue(tx_queue, channel)
++ efx_remove_tx_queue(tx_queue);
++ efx_remove_eventq(channel);
++
++ channel->used_flags = 0;
++}
++
++/**************************************************************************
++ *
++ * Port handling
++ *
++ **************************************************************************/
++
++/* This ensures that the kernel is kept informed (via
++ * netif_carrier_on/off) of the link status, and also maintains the
++ * link status's stop on the port's TX queue.
++ */
++static void efx_link_status_changed(struct efx_nic *efx)
++{
++ unsigned long flags __attribute__ ((unused));
++ int carrier_ok;
++
++ /* Ensure no link status notifications get sent to the OS after the net
++ * device has been unregistered. */
++ if (!efx->net_dev_registered)
++ return;
++
++ carrier_ok = netif_carrier_ok(efx->net_dev) ? 1 : 0;
++ if (efx->link_up != carrier_ok) {
++ efx->n_link_state_changes++;
++
++ if (efx->link_up)
++ netif_carrier_on(efx->net_dev);
++ else
++ netif_carrier_off(efx->net_dev);
++ }
++
++ /* Inform driverlink client */
++ EFX_DL_CALLBACK(efx, link_change, efx->link_up);
++
++ /* Status message for kernel log */
++ if (efx->link_up) {
++ struct mii_if_info *gmii = &efx->mii;
++ unsigned adv, lpa;
++ /* NONE here means direct XAUI from the controller, with no
++ * MDIO-attached device we can query. */
++ if (efx->phy_type != PHY_TYPE_NONE) {
++ adv = gmii_advertised(gmii);
++ lpa = gmii_lpa(gmii);
++ } else {
++ lpa = GM_LPA_10000 | LPA_DUPLEX;
++ adv = lpa;
++ }
++ EFX_INFO(efx, "link up at %dMbps %s-duplex "
++ "(adv %04x lpa %04x) (MTU %d)%s%s%s%s\n",
++ (efx->link_options & GM_LPA_10000 ? 10000 :
++ (efx->link_options & GM_LPA_1000 ? 1000 :
++ (efx->link_options & GM_LPA_100 ? 100 :
++ 10))),
++ (efx->link_options & GM_LPA_DUPLEX ?
++ "full" : "half"),
++ adv, lpa,
++ efx->net_dev->mtu,
++ (efx->loopback_mode ? " [" : ""),
++ (efx->loopback_mode ? LOOPBACK_MODE(efx) : ""),
++ (efx->loopback_mode ? " LOOPBACK]" : ""),
++ (efx->promiscuous ? " [PROMISC]" : ""));
++ } else {
++ EFX_INFO(efx, "link down\n");
++ }
++
++}
++
++/* This call reinitialises the MAC to pick up new PHY settings
++ * To call from a context that cannot sleep use reconfigure_work work item
++ * For on_disabled=1 the caller must be serialised against efx_reset,
++ * ideally by holding the rtnl lock.
++ */
++void efx_reconfigure_port(struct efx_nic *efx, int on_disabled)
++{
++ mutex_lock(&efx->mac_lock);
++
++ EFX_LOG(efx, "reconfiguring MAC from PHY settings\n");
++
++ if (on_disabled)
++ ASSERT_RTNL();
++ else if (!efx->port_enabled)
++ goto out;
++
++ efx->mac_op->reconfigure(efx);
++
++out:
++ /* Inform kernel of loss/gain of carrier */
++ efx_link_status_changed(efx);
++
++ mutex_unlock(&efx->mac_lock);
++}
++
++static void efx_reconfigure_work(struct work_struct *data)
++{
++ struct efx_nic *efx = container_of(data, struct efx_nic,
++ reconfigure_work);
++
++ EFX_LOG(efx, "MAC reconfigure executing on CPU %d\n",
++ raw_smp_processor_id());
++
++ /* Reinitialise MAC to activate new PHY parameters */
++ efx_reconfigure_port(efx, 0);
++}
++
++static int efx_probe_port(struct efx_nic *efx)
++{
++ unsigned char *dev_addr;
++ int rc;
++
++ EFX_LOG(efx, "create port\n");
++
++ /* Connect up MAC/PHY operations table and read MAC address */
++ rc = falcon_probe_port(efx);
++ if (rc)
++ goto err;
++
++ /* Sanity check MAC address */
++ dev_addr = efx->mac_address;
++ if (!is_valid_ether_addr(dev_addr)) {
++ DECLARE_MAC_BUF(mac);
++
++ EFX_ERR(efx, "invalid MAC address %s\n",
++ print_mac(mac, dev_addr));
++ if (!allow_bad_hwaddr) {
++ rc = -EINVAL;
++ goto err;
++ }
++ random_ether_addr(dev_addr);
++ EFX_INFO(efx, "using locally-generated MAC %s\n",
++ print_mac(mac, dev_addr));
++ }
++
++ /* Register debugfs entries */
++ rc = efx_init_debugfs_port(efx);
++ if (rc)
++ goto err;
++
++ return 0;
++
++ err:
++ efx_remove_port(efx);
++ return rc;
++}
++
++static int efx_init_port(struct efx_nic *efx)
++{
++ int rc;
++
++ EFX_LOG(efx, "init port\n");
++
++ /* The default power state is ON */
++ efx->phy_powered = 1;
++
++ /* Initialise the MAC and PHY */
++ rc = efx->mac_op->init(efx);
++ if (rc)
++ return rc;
++
++ efx->port_initialized = 1;
++
++ /* Reconfigure port to program MAC registers */
++ efx->mac_op->reconfigure(efx);
++
++ return 0;
++}
++
++/* Allow efx_reconfigure_port() to run, and propagate delayed changes
++ * to the promiscuous flag to the MAC if needed */
++static void efx_start_port(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "start port\n");
++ ASSERT_RTNL();
++
++ BUG_ON(efx->port_enabled);
++
++ mutex_lock(&efx->mac_lock);
++ efx->port_enabled = 1;
++ mutex_unlock(&efx->mac_lock);
++
++ if (efx->net_dev_registered) {
++ int promiscuous;
++
++ netif_tx_lock_bh(efx->net_dev);
++ promiscuous = (efx->net_dev->flags & IFF_PROMISC) ? 1 : 0;
++ if (efx->promiscuous != promiscuous) {
++ efx->promiscuous = promiscuous;
++ queue_work(efx->workqueue, &efx->reconfigure_work);
++ }
++ netif_tx_unlock_bh(efx->net_dev);
++ }
++}
++
++/* Prevents efx_reconfigure_port() from executing, and prevents
++ * efx_set_multicast_list() from scheduling efx_reconfigure_work.
++ * efx_reconfigure_work can still be scheduled via NAPI processing
++ * until efx_flush_all() is called */
++static void efx_stop_port(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "stop port\n");
++ ASSERT_RTNL();
++
++ mutex_lock(&efx->mac_lock);
++ efx->port_enabled = 0;
++ mutex_unlock(&efx->mac_lock);
++
++ /* Serialise against efx_set_multicast_list() */
++ if (efx->net_dev_registered) {
++ netif_tx_lock_bh(efx->net_dev);
++ netif_tx_unlock_bh(efx->net_dev);
++ }
++}
++
++static void efx_fini_port(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "shut down port\n");
++
++ if (!efx->port_initialized)
++ return;
++
++ efx->mac_op->fini(efx);
++ efx->port_initialized = 0;
++
++ /* Mark the link down */
++ efx->link_up = 0;
++ efx_link_status_changed(efx);
++}
++
++static void efx_remove_port(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "destroying port\n");
++
++ efx_fini_debugfs_port(efx);
++ falcon_remove_port(efx);
++}
++
++/**************************************************************************
++ *
++ * NIC handling
++ *
++ **************************************************************************/
++
++/* This configures the PCI device to enable I/O and DMA. */
++static int efx_init_io(struct efx_nic *efx)
++{
++ struct pci_dev *pci_dev = efx->pci_dev;
++ int rc;
++
++ EFX_LOG(efx, "initialising I/O\n");
++
++ /* Generic device-enabling code */
++ rc = pci_enable_device(pci_dev);
++ if (rc) {
++ EFX_ERR(efx, "failed to enable PCI device\n");
++ goto fail1;
++ }
++
++ pci_set_master(pci_dev);
++
++ /* Set the PCI DMA mask. Try all possibilities from our
++ * genuine mask down to 32 bits, because some architectures
++ * (e.g. x86_64 with iommu_sac_force set) will allow 40 bit
++ * masks event though they reject 46 bit masks.
++ */
++ efx->dma_mask = efx->type->max_dma_mask;
++ while (efx->dma_mask > 0x7fffffffUL) {
++ if (pci_dma_supported(pci_dev, efx->dma_mask) &&
++ ((rc = pci_set_dma_mask(pci_dev, efx->dma_mask)) == 0))
++ break;
++ efx->dma_mask >>= 1;
++ }
++ if (rc) {
++ EFX_ERR(efx, "could not find a suitable DMA mask\n");
++ goto fail2;
++ }
++ EFX_LOG(efx, "using DMA mask %llx\n",
++ (unsigned long long)efx->dma_mask);
++ rc = pci_set_consistent_dma_mask(pci_dev, efx->dma_mask);
++ if (rc) {
++ /* pci_set_consistent_dma_mask() is not *allowed* to
++ * fail with a mask that pci_set_dma_mask() accepted,
++ * but just in case...
++ */
++ EFX_ERR(efx, "failed to set consistent DMA mask\n");
++ goto fail2;
++ }
++
++ /* Get memory base address */
++ efx->membase_phys = pci_resource_start(efx->pci_dev,
++ efx->type->mem_bar);
++#if !defined(EFX_HAVE_MSIX_TABLE_RESERVED)
++ rc = pci_request_region(pci_dev, efx->type->mem_bar, "sfc");
++#else
++ if (!request_mem_region(efx->membase_phys, efx->type->mem_map_size,
++ "sfc"))
++ rc = -EIO;
++#endif
++ if (rc) {
++ EFX_ERR(efx, "request for memory BAR failed\n");
++ rc = -EIO;
++ goto fail3;
++ }
++ efx->membase = ioremap_nocache(efx->membase_phys,
++ efx->type->mem_map_size);
++ if (!efx->membase) {
++ EFX_ERR(efx, "could not map memory BAR %d at %lx+%x\n",
++ efx->type->mem_bar, efx->membase_phys,
++ efx->type->mem_map_size);
++ rc = -ENOMEM;
++ goto fail4;
++ }
++ EFX_LOG(efx, "memory BAR %u at %lx+%x (virtual %p)\n",
++ efx->type->mem_bar, efx->membase_phys, efx->type->mem_map_size,
++ efx->membase);
++
++ return 0;
++
++ fail4:
++ release_mem_region(efx->membase_phys, efx->type->mem_map_size);
++ fail3:
++ efx->membase_phys = 0UL;
++ /* fall-thru */
++ fail2:
++ pci_disable_device(efx->pci_dev);
++ fail1:
++ return rc;
++}
++
++static void efx_fini_io(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "shutting down I/O\n");
++
++ if (efx->membase) {
++ iounmap(efx->membase);
++ efx->membase = NULL;
++ }
++
++ if (efx->membase_phys) {
++#if !defined(EFX_HAVE_MSIX_TABLE_RESERVED)
++ pci_release_region(efx->pci_dev, efx->type->mem_bar);
++#else
++ release_mem_region(efx->membase_phys, efx->type->mem_map_size);
++#endif
++ efx->membase_phys = 0UL;
++ }
++
++ pci_disable_device(efx->pci_dev);
++}
++
++/* Probe the number and type of interrupts we are able to obtain. */
++static int efx_probe_interrupts(struct efx_nic *efx)
++{
++ struct msix_entry xentries[EFX_MAX_CHANNELS];
++ int rc, i;
++
++ /* Select number of used RSS queues */
++ /* TODO: Can we react to CPU hotplug? */
++ if (rss_cpus == 0)
++ rss_cpus = num_online_cpus();
++
++ efx->rss_queues = 1;
++ if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
++ unsigned int max_channel = efx->type->phys_addr_channels - 1;
++
++ BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX));
++ efx->rss_queues = min(max_channel + 1, rss_cpus);
++ efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS);
++ }
++
++ /* Determine how many RSS queues we can use, and mark channels
++ * with the appropriate interrupt state */
++ if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
++ /* Build MSI request structure */
++ for (i = 0; i < efx->rss_queues; i++)
++ xentries[i].entry = i;
++
++ /* Request maximum number of MSI interrupts */
++ rc = pci_enable_msix(efx->pci_dev, xentries, efx->rss_queues);
++ if (rc > 0) {
++ EFX_BUG_ON_PARANOID(rc >= efx->rss_queues);
++ efx->rss_queues = rc;
++ rc = pci_enable_msix(efx->pci_dev, xentries,
++ efx->rss_queues);
++ }
++ if (rc == 0) {
++ for (i = 0; i < efx->rss_queues; i++) {
++ efx->channel[i].has_interrupt = 1;
++ efx->channel[i].irq = xentries[i].vector;
++ }
++ } else {
++ /* Fall back to single channel MSI */
++ efx->interrupt_mode = EFX_INT_MODE_MSI;
++ EFX_ERR(efx, "could not enable MSI-X\n");
++ }
++ }
++
++ /* Try single interrupt MSI */
++ if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
++ efx->rss_queues = 1;
++ rc = pci_enable_msi(efx->pci_dev);
++ if (rc == 0) {
++ efx->channel[0].irq = efx->pci_dev->irq;
++ efx->channel[0].has_interrupt = 1;
++ } else {
++ EFX_ERR(efx, "could not enable MSI\n");
++ efx->interrupt_mode = EFX_INT_MODE_LEGACY;
++ }
++ }
++
++ /* Assume legacy interrupts */
++ if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
++ /* Every channel is interruptible */
++ for (i = 0; i < EFX_MAX_CHANNELS; i++)
++ efx->channel[i].has_interrupt = 1;
++ efx->legacy_irq = efx->pci_dev->irq;
++ }
++
++ return 0;
++}
++
++static void efx_remove_interrupts(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ /* Remove MSI/MSI-X interrupts */
++ efx_for_each_channel_with_interrupt(channel, efx)
++ channel->irq = 0;
++ pci_disable_msi(efx->pci_dev);
++ pci_disable_msix(efx->pci_dev);
++
++ /* Remove legacy interrupt */
++ efx->legacy_irq = 0;
++}
++
++/* Select number of used resources
++ * Should be called after probe_interrupts()
++ */
++static int efx_select_used(struct efx_nic *efx)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ int i;
++
++ /* TX queues. One per port per channel with TX capability
++ * (more than one per port won't work on Linux, due to out
++ * of order issues... but will be fine on Solaris)
++ */
++ tx_queue = &efx->tx_queue[0];
++
++ /* Perform this for each channel with TX capabilities.
++ * At the moment, we only support a single TX queue
++ */
++ tx_queue->used = 1;
++ if ((!EFX_INT_MODE_USE_MSI(efx)) && separate_tx_and_rx_channels)
++ tx_queue->channel = &efx->channel[1];
++ else
++ tx_queue->channel = &efx->channel[0];
++ tx_queue->channel->used_flags |= EFX_USED_BY_TX;
++ tx_queue++;
++
++ /* RX queues. Each has a dedicated channel. */
++ for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
++ rx_queue = &efx->rx_queue[i];
++
++ if (i < efx->rss_queues) {
++ rx_queue->used = 1;
++ /* If we allow multiple RX queues per channel
++ * we need to decide that here
++ */
++ rx_queue->channel = &efx->channel[rx_queue->queue];
++ rx_queue->channel->used_flags |= EFX_USED_BY_RX;
++ rx_queue++;
++ }
++ }
++ return 0;
++}
++
++static int efx_probe_nic(struct efx_nic *efx)
++{
++ int rc;
++
++ EFX_LOG(efx, "creating NIC\n");
++
++ /* Carry out hardware-type specific initialisation */
++ rc = falcon_probe_nic(efx);
++ if (rc)
++ goto fail1;
++
++ /* Determine the number of channels and RX queues by trying to hook
++ * in MSI-X interrupts. */
++ rc = efx_probe_interrupts(efx);
++ if (rc)
++ goto fail2;
++
++ /* Determine number of RX queues and TX queues */
++ rc = efx_select_used(efx);
++ if (rc)
++ goto fail3;
++
++ /* Register debugfs entries */
++ rc = efx_init_debugfs_nic(efx);
++ if (rc)
++ goto fail4;
++ /* Initialise the interrupt moderation settings */
++ efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec);
++
++ return 0;
++
++ fail4:
++ /* fall-thru */
++ fail3:
++ efx_remove_interrupts(efx);
++ fail2:
++ falcon_remove_nic(efx);
++ fail1:
++ return rc;
++}
++
++static void efx_remove_nic(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "destroying NIC\n");
++
++ efx_remove_interrupts(efx);
++ falcon_remove_nic(efx);
++
++ efx_fini_debugfs_nic(efx);
++}
++
++/**************************************************************************
++ *
++ * NIC startup/shutdown
++ *
++ *************************************************************************/
++
++static int efx_probe_all(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ int rc;
++
++ /* Create NIC */
++ rc = efx_probe_nic(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to create NIC\n");
++ goto fail1;
++ }
++
++ /* Create port */
++ rc = efx_probe_port(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to create port\n");
++ goto fail2;
++ }
++
++ /* Create channels */
++ efx_for_each_channel(channel, efx) {
++ rc = efx_probe_channel(channel);
++ if (rc) {
++ EFX_ERR(efx, "failed to create channel %d\n",
++ channel->channel);
++ goto fail3;
++ }
++ }
++
++ return 0;
++
++ fail3:
++ efx_for_each_channel(channel, efx)
++ efx_remove_channel(channel);
++ fail2:
++ efx_remove_port(efx);
++ fail1:
++ return rc;
++}
++
++/* Called after previous invocation(s) of efx_stop_all, restarts the
++ * port, kernel transmit queue, NAPI processing and hardware interrupts.
++ * This function is safe to call multiple times when the NIC is in any
++ * state. */
++static void efx_start_all(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ ASSERT_RTNL();
++
++ /* Check that it is appropriate to restart the interface. All
++ * of these flags are safe to read under just the rtnl lock */
++ if (efx->port_enabled)
++ return;
++ if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT))
++ return;
++ if (efx->net_dev_registered && !netif_running(efx->net_dev))
++ return;
++
++ /* Mark the port as enabled so port reconfigurations can start, then
++ * restart the transmit interface early so the watchdog timer stops */
++ efx_start_port(efx);
++ efx_wake_queue(efx);
++
++ efx_for_each_channel(channel, efx)
++ efx_start_channel(channel);
++
++ falcon_enable_interrupts(efx);
++
++ /* Start hardware monitor if we're in RUNNING */
++ if (efx->state == STATE_RUNNING)
++ queue_delayed_work(efx->workqueue, &efx->monitor_work,
++ efx_monitor_interval);
++}
++
++/* Flush all delayed work. Should only be called when no more delayed work
++ * will be scheduled. This doesn't flush pending online resets (efx_reset),
++ * since we're holding the rtnl_lock at this point. */
++static void efx_flush_all(struct efx_nic *efx)
++{
++#if defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ struct efx_rx_queue *rx_queue;
++
++ /* Make sure the hardware monitor is stopped */
++ cancel_delayed_work_sync(&efx->monitor_work);
++
++ /* Ensure that all RX slow refills are complete. */
++ efx_for_each_rx_queue(rx_queue, efx) {
++ cancel_delayed_work_sync(&rx_queue->work);
++ }
++#endif
++
++#if defined(EFX_USE_CANCEL_WORK_SYNC)
++ /* Stop scheduled port reconfigurations */
++ cancel_work_sync(&efx->reconfigure_work);
++#endif
++
++#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ /* Ensure that the hardware monitor and asynchronous port
++ * reconfigurations are complete, which are the only two consumers
++ * of efx->workqueue. Since the hardware monitor runs on a long period,
++ * we put in some effort to cancel the delayed work safely rather
++ * than just flushing the queue twice (which is guaranteed to flush
++ * all the work since both efx_monitor and efx_reconfigure_work disarm
++ * if !efx->port_enabled. */
++ if (timer_pending(&efx->monitor_work.timer))
++ cancel_delayed_work(&efx->monitor_work);
++ flush_workqueue(efx->workqueue);
++ if (timer_pending(&efx->monitor_work.timer))
++ cancel_delayed_work(&efx->monitor_work);
++ flush_workqueue(efx->workqueue);
++
++ /* efx_rx_work will disarm if !channel->enabled, so we can just
++ * flush the refill workqueue twice as well. */
++ flush_workqueue(efx->refill_workqueue);
++ flush_workqueue(efx->refill_workqueue);
++#endif
++}
++
++/* Quiesce hardware and software without bringing the link down.
++ * Safe to call multiple times, when the nic and interface is in any
++ * state. The caller is guaranteed to subsequently be in a position
++ * to modify any hardware and software state they see fit without
++ * taking locks. */
++static void efx_stop_all(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ ASSERT_RTNL();
++
++ /* port_enabled can be read safely under the rtnl lock */
++ if (!efx->port_enabled)
++ return;
++
++ /* Disable interrupts and wait for ISR to complete */
++ falcon_disable_interrupts(efx);
++ if (efx->legacy_irq)
++ synchronize_irq(efx->legacy_irq);
++ efx_for_each_channel_with_interrupt(channel, efx)
++ if (channel->irq)
++ synchronize_irq(channel->irq);
++
++ /* Stop all synchronous port reconfigurations. */
++ efx_stop_port(efx);
++
++ /* Stop all NAPI processing and synchronous rx refills */
++ efx_for_each_channel(channel, efx)
++ efx_stop_channel(channel);
++
++ /* Flush reconfigure_work, refill_workqueue, monitor_work */
++ efx_flush_all(efx);
++
++ /* Stop the kernel transmit interface late, so the watchdog
++ * timer isn't ticking over the flush */
++ efx_stop_queue(efx);
++ if (efx->net_dev_registered) {
++ netif_tx_lock_bh(efx->net_dev);
++ netif_tx_unlock_bh(efx->net_dev);
++ }
++}
++
++static void efx_remove_all(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ efx_for_each_channel(channel, efx)
++ efx_remove_channel(channel);
++ efx_remove_port(efx);
++ efx_remove_nic(efx);
++}
++
++static int efx_run_selftests(struct efx_nic *efx)
++{
++ struct efx_self_tests tests;
++ unsigned modes = efx->startup_loopbacks & efx->loopback_modes;
++ int rc;
++
++ rc = efx_online_test(efx, &tests);
++ if (rc) {
++ EFX_ERR(efx, "failed self-tests with interrupt_mode of %s\n",
++ INT_MODE(efx));
++ goto fail;
++ }
++
++ if (onload_offline_selftest && modes) {
++ /* Run offline self test */
++ EFX_LOG(efx, "performing on-load offline self-tests\n");
++ rc = efx_offline_test(efx, &tests, modes);
++ EFX_LOG(efx, "%s on-load offline self-tests\n",
++ rc ? "FAILED" : "PASSED");
++ if (rc)
++ goto fail;
++ }
++
++ return 0;
++
++ fail:
++ EFX_ERR(efx, "self-tests failed. Given up!\n");
++ if (allow_load_on_failure)
++ rc = 0;
++
++ return rc;
++}
++
++int efx_flush_queues(struct efx_nic *efx)
++{
++ int rc;
++
++ ASSERT_RTNL();
++
++ efx_stop_all(efx);
++
++ /* We can't just flush the tx queues because the event queues
++ * may contain tx completions from that queue. Just flush everything */
++ efx_fini_channels(efx);
++ rc = efx_init_channels(efx);
++ if (rc) {
++ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
++ return rc;
++ }
++
++ efx_start_all(efx);
++
++ return 0;
++}
++
++/**************************************************************************
++ *
++ * Interrupt moderation
++ *
++ **************************************************************************/
++
++/* Set interrupt moderation parameters */
++void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs)
++{
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++
++ ASSERT_RTNL();
++
++ efx_for_each_tx_queue(tx_queue, efx)
++ tx_queue->channel->irq_moderation = tx_usecs;
++
++ efx_for_each_rx_queue(rx_queue, efx)
++ rx_queue->channel->irq_moderation = rx_usecs;
++}
++
++/**************************************************************************
++ *
++ * Hardware monitor
++ *
++ **************************************************************************/
++
++/* Run periodically off the general workqueue. Serialised against
++ * efx_reconfigure_port via the mac_lock */
++static void efx_monitor(struct work_struct *data)
++{
++#if !defined(EFX_NEED_WORK_API_WRAPPERS)
++ struct efx_nic *efx = container_of(data, struct efx_nic,
++ monitor_work.work);
++#else
++ struct efx_nic *efx = container_of(data, struct efx_nic,
++ monitor_work);
++#endif
++ int rc = 0;
++
++ EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
++ raw_smp_processor_id());
++
++
++#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ /* Without cancel_delayed_work_sync(), we have to make sure that
++ * we don't rearm when port_enabled == 0 */
++ mutex_lock(&efx->mac_lock);
++ if (!efx->port_enabled) {
++ mutex_unlock(&efx->mac_lock);
++ return;
++ }
++
++ rc = efx->mac_op->check_hw(efx);
++#else
++ /* If the mac_lock is already held then it is likely a port
++ * reconfiguration is already in place, which will likely do
++ * most of the work of check_hw() anyway. */
++ if (!mutex_trylock(&efx->mac_lock)) {
++ queue_delayed_work(efx->workqueue, &efx->monitor_work,
++ efx_monitor_interval);
++ return;
++ }
++
++ if (efx->port_enabled)
++ rc = efx->mac_op->check_hw(efx);
++#endif
++ mutex_unlock(&efx->mac_lock);
++
++ if (rc) {
++ if (monitor_reset) {
++ EFX_ERR(efx, "hardware monitor detected a fault: "
++ "triggering reset\n");
++ efx_schedule_reset(efx, RESET_TYPE_MONITOR);
++ } else {
++ EFX_ERR(efx, "hardware monitor detected a fault, "
++ "skipping reset\n");
++ }
++ }
++
++ queue_delayed_work(efx->workqueue, &efx->monitor_work,
++ efx_monitor_interval);
++}
++
++/**************************************************************************
++ *
++ * ioctls
++ *
++ *************************************************************************/
++
++/* Net device ioctl
++ * Context: process, rtnl_lock() held.
++ */
++static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc;
++
++ ASSERT_RTNL();
++
++ switch (cmd) {
++ case SIOCGMIIPHY:
++ case SIOCGMIIREG:
++ rc = generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL);
++ break;
++ case SIOCSMIIREG:
++ rc = generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL);
++ efx_reconfigure_port(efx, 0);
++ break;
++ default:
++ rc = -EOPNOTSUPP;
++ }
++
++ return rc;
++}
++
++/**************************************************************************
++ *
++ * NAPI interface
++ *
++ **************************************************************************/
++
++/* Allocate the NAPI dev's.
++ * Called after we know how many channels there are.
++ */
++static int efx_init_napi(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ int rc;
++
++ ASSERT_RTNL();
++
++ /* Allocate the NAPI dev for the port */
++ efx->net_dev = alloc_etherdev(0);
++ if (!efx->net_dev) {
++ rc = -ENOMEM;
++ goto err;
++ }
++ efx->net_dev->priv = efx;
++ efx->mii.dev = efx->net_dev;
++
++ /* Set features based on module parameters and DMA mask.
++ * Enable DMA to ZONE_HIGHMEM if the NIC can access all memory
++ * directly. This only has an effect on 32-bit systems and
++ * PAE on x86 limits memory to 64GB so 40 bits is plenty to
++ * address everything. If the device can't address 40 bits
++ * then it's safest to turn NETIF_F_HIGHDMA off because this
++ * might be a PAE system with more than 4G of RAM and a 32-bit
++ * NIC. The use of EFX_DMA_MASK is to eliminate compiler
++ * warnings on platforms where dma_addr_t is 32-bit. We
++ * assume that in those cases we can access all memory
++ * directly if our DMA mask is all ones. */
++ efx->net_dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
++ if (efx->dma_mask >= EFX_DMA_MASK(DMA_40BIT_MASK))
++ efx->net_dev->features |= NETIF_F_HIGHDMA;
++
++ /* Copy MAC address */
++ memcpy(&efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
++
++ /* Allocate the per channel devs */
++ efx_for_each_channel(channel, efx) {
++#if !defined(EFX_HAVE_OLD_NAPI)
++ channel->napi_dev = efx->net_dev;
++#else
++ channel->napi_dev = alloc_etherdev(0);
++ if (!channel->napi_dev) {
++ rc = -ENOMEM;
++ goto err;
++ }
++ channel->napi_dev->priv = channel;
++ atomic_set(&channel->napi_dev->refcnt, 1);
++#endif
++ }
++
++ return 0;
++ err:
++ efx_fini_napi(efx);
++ return rc;
++}
++
++/* Free the NAPI state for the port and channels */
++static void efx_fini_napi(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++
++ ASSERT_RTNL();
++
++ efx_for_each_channel(channel, efx) {
++ /* Finish per channel NAPI */
++#if defined(EFX_HAVE_OLD_NAPI)
++ if (channel->napi_dev) {
++ channel->napi_dev->priv = NULL;
++ free_netdev(channel->napi_dev);
++ }
++#endif
++ channel->napi_dev = NULL;
++ }
++
++ /* Finish port NAPI */
++ if (efx->net_dev) {
++ efx->net_dev->priv = NULL;
++ free_netdev(efx->net_dev);
++ efx->net_dev = NULL;
++ }
++}
++
++/**************************************************************************
++ *
++ * Kernel netpoll interface
++ *
++ *************************************************************************/
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++
++/* Although in the common case interrupts will be disabled, this is not
++ * guaranteed. However, all our work happens inside the NAPI callback,
++ * so no locking is required.
++ */
++static void efx_netpoll(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_channel *channel;
++
++ efx_for_each_channel_with_interrupt(channel, efx)
++ efx_schedule_channel(channel);
++}
++
++#endif
++
++/**************************************************************************
++ *
++ * Kernel net device interface
++ *
++ *************************************************************************/
++
++/* Context: process, rtnl_lock() held. */
++static int efx_net_open(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ ASSERT_RTNL();
++
++ EFX_LOG(efx, "opening device %s on CPU %d\n", net_dev->name,
++ raw_smp_processor_id());
++ efx_start_all(efx);
++ return 0;
++}
++
++/* Context: process, rtnl_lock() held.
++ * Note that the kernel will ignore our return code; this method
++ * should really be a void.
++ */
++static int efx_net_stop(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc;
++
++ EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name,
++ raw_smp_processor_id());
++
++ /* Stop device and flush all the channels */
++ efx_stop_all(efx);
++ efx_fini_channels(efx);
++ rc = efx_init_channels(efx);
++ if (rc)
++ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
++
++ return 0;
++}
++
++/* Context: process, dev_base_lock held, non-blocking.
++ * Statistics are taken directly from the MAC.
++ */
++static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_mac_stats *mac_stats = &efx->mac_stats;
++ struct net_device_stats *stats = &efx->stats;
++
++ if (!spin_trylock(&efx->stats_lock))
++ return stats;
++ if (efx->state == STATE_RUNNING)
++ efx->mac_op->update_stats(efx);
++ spin_unlock(&efx->stats_lock);
++
++ stats->rx_packets = mac_stats->rx_packets;
++ stats->tx_packets = mac_stats->tx_packets;
++ stats->rx_bytes = mac_stats->rx_bytes;
++ stats->tx_bytes = mac_stats->tx_bytes;
++ stats->tx_errors = mac_stats->tx_bad;
++ stats->multicast = mac_stats->rx_multicast;
++ stats->collisions = mac_stats->tx_collision;
++ stats->rx_length_errors = mac_stats->rx_gtjumbo;
++ stats->rx_over_errors = mac_stats->rx_overflow;
++ stats->rx_crc_errors = mac_stats->rx_bad;
++ stats->rx_frame_errors = mac_stats->rx_align_error;
++ stats->rx_fifo_errors = 0;
++ stats->rx_missed_errors = mac_stats->rx_missed;
++ stats->rx_errors = (stats->rx_length_errors +
++ stats->rx_over_errors +
++ stats->rx_crc_errors +
++ stats->rx_frame_errors +
++ stats->rx_fifo_errors +
++ stats->rx_missed_errors +
++ mac_stats->rx_symbol_error);
++ stats->tx_aborted_errors = 0;
++ stats->tx_carrier_errors = 0;
++ stats->tx_fifo_errors = 0;
++ stats->tx_heartbeat_errors = 0;
++ stats->tx_window_errors = 0;
++
++ return stats;
++}
++
++/* Context: netif_tx_lock held, BHs disabled. */
++static void efx_watchdog(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d: %s\n",
++ atomic_read(&efx->netif_stop_count), efx->port_enabled,
++ monitor_reset ? "resetting channels" : "skipping reset");
++
++ if (monitor_reset)
++ efx_schedule_reset(efx, RESET_TYPE_MONITOR);
++}
++
++
++/* Context: process, rtnl_lock() held. */
++static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc = 0;
++
++ ASSERT_RTNL();
++
++ if (new_mtu > EFX_MAX_MTU)
++ return -EINVAL;
++
++ efx_stop_all(efx);
++
++ /* Ask driverlink client if we can change MTU */
++ rc = EFX_DL_CALLBACK(efx, request_mtu, new_mtu);
++ if (rc) {
++ EFX_ERR(efx, "MTU change vetoed by driverlink %s driver\n",
++ efx->dl_cb_dev.request_mtu->driver->name);
++ goto out;
++ }
++
++ EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
++
++ efx_fini_channels(efx);
++ net_dev->mtu = new_mtu;
++ rc = efx_init_channels(efx);
++ if (rc)
++ goto fail;
++
++ /* Reconfigure the MAC */
++ efx_reconfigure_port(efx, 1);
++
++ /* Notify driverlink client of new MTU */
++ EFX_DL_CALLBACK(efx, mtu_changed, new_mtu);
++
++ efx_start_all(efx);
++
++ out:
++ return rc;
++
++ fail:
++ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
++ return rc;
++}
++
++static int efx_set_mac_address(struct net_device *net_dev, void *data)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct sockaddr *addr = data;
++ char *new_addr = addr->sa_data;
++
++ ASSERT_RTNL();
++
++ if (!is_valid_ether_addr(new_addr)) {
++ DECLARE_MAC_BUF(mac);
++ EFX_ERR(efx, "invalid ethernet MAC address requested: %s\n",
++ print_mac(mac, new_addr));
++ return -EINVAL;
++ }
++
++ memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);
++
++ /* Reconfigure the MAC */
++ efx_reconfigure_port(efx, 1);
++
++ return 0;
++}
++
++/* Context: netif_tx_lock held, BHs disabled. */
++static void efx_set_multicast_list(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct dev_mc_list *mc_list = net_dev->mc_list;
++ union efx_multicast_hash *mc_hash = &efx->multicast_hash;
++ unsigned long flags __attribute__ ((unused));
++ int promiscuous;
++ u32 crc;
++ int bit;
++ int i;
++
++ /* Set per-MAC promiscuity flag and reconfigure MAC if necessary */
++ promiscuous = (net_dev->flags & IFF_PROMISC) ? 1 : 0;
++ if (efx->promiscuous != promiscuous) {
++ if (efx->port_enabled) {
++ efx->promiscuous = promiscuous;
++ queue_work(efx->workqueue, &efx->reconfigure_work);
++ }
++ }
++
++ /* Build multicast hash table */
++ if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
++ memset(mc_hash, 0xff, sizeof(*mc_hash));
++ } else {
++ memset(mc_hash, 0x00, sizeof(*mc_hash));
++ for (i = 0; i < net_dev->mc_count; i++) {
++ crc = ether_crc_le(ETH_ALEN, mc_list->dmi_addr);
++ bit = (crc & ((1 << EFX_MCAST_HASH_BITS) - 1));
++ set_bit_le(bit, (void *)mc_hash);
++ mc_list = mc_list->next;
++ }
++ }
++
++ /* Create and activate new global multicast hash table */
++ falcon_set_multicast_hash(efx);
++}
++
++/* Handle net device notifier events */
++static int efx_netdev_event(struct notifier_block *this,
++ unsigned long event, void *ptr)
++{
++ struct net_device *net_dev = (struct net_device *)ptr;
++
++ if (net_dev->open == efx_net_open && event == NETDEV_CHANGENAME) {
++ struct efx_nic *efx = net_dev->priv;
++
++ strcpy(efx->name, net_dev->name);
++ efx_fini_debugfs_netdev(net_dev);
++ efx_init_debugfs_netdev(net_dev);
++ }
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block efx_netdev_notifier = {
++ .notifier_call = efx_netdev_event,
++};
++
++static int efx_register_netdev(struct efx_nic *efx)
++{
++ struct net_device *net_dev = efx->net_dev;
++ int rc;
++
++ net_dev->watchdog_timeo = 5 * HZ;
++ net_dev->irq = efx->pci_dev->irq;
++ net_dev->open = efx_net_open;
++ net_dev->stop = efx_net_stop;
++ net_dev->get_stats = efx_net_stats;
++ net_dev->tx_timeout = &efx_watchdog;
++ net_dev->hard_start_xmit = efx_hard_start_xmit;
++ net_dev->do_ioctl = efx_ioctl;
++ net_dev->change_mtu = efx_change_mtu;
++ net_dev->set_mac_address = efx_set_mac_address;
++ net_dev->set_multicast_list = efx_set_multicast_list;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ net_dev->poll_controller = efx_netpoll;
++#endif
++ SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
++ SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
++
++ /* Always start with carrier off; PHY events will detect the link */
++ netif_carrier_off(efx->net_dev);
++
++ BUG_ON(efx->net_dev_registered);
++
++ /* Clear MAC statistics */
++ efx->mac_op->update_stats(efx);
++ memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
++
++ rc = register_netdev(net_dev);
++ if (rc) {
++ EFX_ERR(efx, "could not register net dev\n");
++ return rc;
++ }
++ strcpy(efx->name, net_dev->name);
++
++ /* Create debugfs symlinks */
++ rc = efx_init_debugfs_netdev(net_dev);
++ if (rc) {
++ EFX_ERR(efx, "failed to init net dev debugfs\n");
++ unregister_netdev(efx->net_dev);
++ return rc;
++ }
++
++ /* Allow link change notifications to be sent to the operating
++ * system. The must happen after register_netdev so that
++ * there are no outstanding link changes if that call fails.
++ * It must happen before efx_reconfigure_port so that the
++ * initial state of the link is reported. */
++ mutex_lock(&efx->mac_lock);
++ efx->net_dev_registered = 1;
++ mutex_unlock(&efx->mac_lock);
++
++ /* Safety net: in case we don't get a PHY event */
++ rtnl_lock();
++ efx_reconfigure_port(efx, 1);
++ rtnl_unlock();
++
++ EFX_LOG(efx, "registered\n");
++
++ return 0;
++}
++
++static void efx_unregister_netdev(struct efx_nic *efx)
++{
++ int was_registered = efx->net_dev_registered;
++ struct efx_tx_queue *tx_queue;
++
++ if (!efx->net_dev)
++ return;
++
++ BUG_ON(efx->net_dev->priv != efx);
++
++ /* SFC Bug 5356: Ensure that no more link status notifications get
++ * sent to the stack. Bad things happen if there's an
++ * outstanding notification after the net device is freed, but
++ * they only get flushed out by unregister_netdev, not by
++ * free_netdev. */
++ mutex_lock(&efx->mac_lock);
++ efx->net_dev_registered = 0;
++ mutex_unlock(&efx->mac_lock);
++
++ /* Free up any skbs still remaining. This has to happen before
++ * we try to unregister the netdev as running their destructors
++ * may be needed to get the device ref. count to 0. */
++ efx_for_each_tx_queue(tx_queue, efx)
++ efx_release_tx_buffers(tx_queue);
++
++ if (was_registered) {
++ strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
++ efx_fini_debugfs_netdev(efx->net_dev);
++ unregister_netdev(efx->net_dev);
++ }
++}
++
++/**************************************************************************
++ *
++ * Device reset and suspend
++ *
++ **************************************************************************/
++
++/* This suspends the device (and acquires the suspend lock) without
++ * flushing the descriptor queues. It is included for the convenience
++ * of the driverlink layer.
++ */
++void efx_suspend(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "suspending operations\n");
++
++ down(&efx->suspend_lock);
++
++ rtnl_lock();
++ efx_stop_all(efx);
++}
++
++void efx_resume(struct efx_nic *efx)
++{
++ EFX_LOG(efx, "resuming operations\n");
++
++ efx_start_all(efx);
++ rtnl_unlock();
++
++ up(&efx->suspend_lock);
++}
++
++/* The final hardware and software finalisation before reset.
++ * This function does not handle serialisation with the kernel, it
++ * assumes the caller has done this */
++static int efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
++{
++ int rc;
++
++ ASSERT_RTNL();
++
++ rc = efx->mac_op->get_settings(efx, ecmd);
++ if (rc) {
++ EFX_ERR(efx, "could not back up PHY settings\n");
++ goto fail;
++ }
++
++ efx_fini_channels(efx);
++ return 0;
++
++ fail:
++ return rc;
++}
++
++/* The first part of software initialisation after a hardware reset
++ * This function does not handle serialisation with the kernel, it
++ * assumes the caller has done this */
++static int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd)
++{
++ int rc;
++
++ rc = efx_init_channels(efx);
++ if (rc)
++ goto fail1;
++
++ /* In an INVISIBLE_RESET there might not be a link state transition,
++ * so we push the multicast list here. */
++ falcon_set_multicast_hash(efx);
++
++ /* Restore MAC and PHY settings. */
++ rc = efx->mac_op->set_settings(efx, ecmd);
++ if (rc) {
++ EFX_ERR(efx, "could not restore PHY settings\n");
++ goto fail2;
++ }
++
++ return 0;
++
++ fail2:
++ efx_fini_channels(efx);
++ fail1:
++ return rc;
++}
++
++/* Reset the NIC as transparently as possible. Do not reset the PHY
++ * Note that the reset may fail, in which case the card will be left
++ * in a most-probably-unusable state.
++ *
++ * This function will sleep. You cannot reset from within an atomic
++ * state; use efx_schedule_reset() instead.
++ */
++static int efx_reset(struct efx_nic *efx)
++{
++ struct ethtool_cmd ecmd;
++ unsigned long flags __attribute__ ((unused));
++ enum reset_type method = efx->reset_pending;
++ int rc;
++
++ efx_dl_reset_lock();
++
++ rc = down_interruptible(&efx->suspend_lock);
++ if (rc) {
++ EFX_ERR(efx, "reset aborted by signal\n");
++ goto unlock_dl_lock;
++ }
++
++ /* We've got suspend_lock, which means we can only be in
++ * STATE_RUNNING or STATE_FINI. Don't clear
++ * efx->reset_pending, since this flag indicates that we
++ * should retry device initialisation.
++ */
++ if (efx->state != STATE_RUNNING) {
++ EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
++ goto unlock_suspend_lock;
++ }
++
++ /* Notify driverlink clients of imminent reset. */
++ efx_dl_reset_suspend(efx);
++ rtnl_lock();
++
++ efx->state = STATE_RESETTING;
++ EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method));
++
++ /* The net_dev->get_stats handler is quite slow, and will fail
++ * if a fetch is pending over reset. Serialise against it. */
++ spin_lock(&efx->stats_lock);
++ spin_unlock(&efx->stats_lock);
++
++ efx_stop_all(efx);
++ mutex_lock(&efx->mac_lock);
++
++ rc = efx_reset_down(efx, &ecmd);
++ if (rc)
++ goto fail1;
++ falcon_fini_nic(efx);
++
++ rc = falcon_reset_hw(efx, method);
++ if (rc) {
++ EFX_ERR(efx, "failed to reset hardware\n");
++ goto fail2;
++ }
++
++ /* Allow resets to be rescheduled. */
++ efx->reset_pending = RESET_TYPE_NONE;
++
++ /* Reinitialise bus-mastering, which may have been turned off before
++ * the reset was scheduled. This is still appropriate, even in the
++ * RESET_TYPE_DISABLE since this driver generally assumes the hardware
++ * can respond to requests. */
++ pci_set_master(efx->pci_dev);
++
++ /* Reinitialise device. This is appropriate in the RESET_TYPE_DISABLE
++ * case so the driver can talk to external SRAM */
++ rc = falcon_init_nic(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to initialise NIC\n");
++ goto fail3;
++ }
++
++ /* Leave device stopped if necessary */
++ if (method == RESET_TYPE_DISABLE) {
++ /* Reinitialise the device anyway so the driver unload sequence
++ * can talk to the external SRAM */
++ (void) falcon_init_nic(efx);
++ rc = -EIO;
++ goto fail4;
++ }
++
++ rc = efx_reset_up(efx, &ecmd);
++ if (rc)
++ goto fail5;
++
++ mutex_unlock(&efx->mac_lock);
++ efx_reconfigure_port(efx, 1);
++ EFX_LOG(efx, "reset complete\n");
++
++ efx->state = STATE_RUNNING;
++ efx_start_all(efx);
++
++ rtnl_unlock();
++
++ goto notify;
++
++ fail5:
++ fail4:
++ fail3:
++ fail2:
++ fail1:
++ EFX_ERR(efx, "has been disabled\n");
++ efx->state = STATE_DISABLED;
++
++ /* Remove the net_dev */
++ mutex_unlock(&efx->mac_lock);
++ rtnl_unlock();
++ efx_unregister_netdev(efx);
++ efx_fini_port(efx);
++
++ notify:
++ /* Notify driverlink clients of completed reset */
++ efx_dl_reset_resume(efx, (rc == 0));
++
++ unlock_suspend_lock:
++ up(&efx->suspend_lock);
++
++ unlock_dl_lock:
++ efx_dl_reset_unlock();
++
++ return rc;
++}
++
++/* The worker thread exists so that code that cannot sleep can
++ * schedule a reset for later.
++ */
++static void efx_reset_work(struct work_struct *data)
++{
++ struct efx_nic *nic = container_of(data, struct efx_nic, reset_work);
++
++ efx_reset(nic);
++}
++
++void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
++{
++ enum reset_type method;
++
++ if (efx->reset_pending != RESET_TYPE_NONE) {
++ EFX_INFO(efx, "quenching already scheduled reset\n");
++ return;
++ }
++
++ switch (type) {
++ case RESET_TYPE_INVISIBLE:
++ case RESET_TYPE_ALL:
++ case RESET_TYPE_WORLD:
++ case RESET_TYPE_DISABLE:
++ method = type;
++ break;
++ case RESET_TYPE_RX_RECOVERY:
++ case RESET_TYPE_RX_DESC_FETCH:
++ case RESET_TYPE_TX_DESC_FETCH:
++ method = RESET_TYPE_INVISIBLE;
++ break;
++ default:
++ method = RESET_TYPE_ALL;
++ break;
++ }
++
++ if (method != type)
++ EFX_LOG(efx, "scheduling %s reset for %s\n",
++ RESET_TYPE(method), RESET_TYPE(type));
++ else
++ EFX_LOG(efx, "scheduling %s reset\n", RESET_TYPE(method));
++
++ efx->reset_pending = method;
++
++#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ queue_work(efx->reset_workqueue, &efx->reset_work);
++#else
++ queue_work(efx->workqueue, &efx->reset_work);
++#endif
++}
++
++/**************************************************************************
++ *
++ * List of NICs we support
++ *
++ **************************************************************************/
++
++enum efx_type_index {
++ EFX_TYPE_FALCON_A = 0,
++ EFX_TYPE_FALCON_B = 1,
++};
++
++static struct efx_nic_type *efx_nic_types[] = {
++ [EFX_TYPE_FALCON_A] = &falcon_a_nic_type,
++ [EFX_TYPE_FALCON_B] = &falcon_b_nic_type,
++};
++
++
++/* PCI device ID table */
++static struct pci_device_id efx_pci_table[] __devinitdata = {
++ {EFX_VENDID_SFC, FALCON_A_P_DEVID, PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0, EFX_TYPE_FALCON_A},
++ {EFX_VENDID_SFC, FALCON_B_P_DEVID, PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0, EFX_TYPE_FALCON_B},
++ {0} /* end of list */
++};
++
++/**************************************************************************
++ *
++ * Dummy PHY/MAC/Board operations
++ *
++ * Can be used where the MAC does not implement this operation
++ * Needed so all function pointers are valid and do not have to be tested
++ * before use
++ *
++ **************************************************************************/
++int efx_port_dummy_op_int(struct efx_nic *efx)
++{
++ return 0;
++}
++void efx_port_dummy_op_void(struct efx_nic *efx) {}
++void efx_port_dummy_op_blink(struct efx_nic *efx, int blink) {}
++
++static struct efx_mac_operations efx_dummy_mac_operations = {
++ .init = efx_port_dummy_op_int,
++ .reconfigure = efx_port_dummy_op_void,
++ .fini = efx_port_dummy_op_void,
++};
++
++static struct efx_phy_operations efx_dummy_phy_operations = {
++ .init = efx_port_dummy_op_int,
++ .reconfigure = efx_port_dummy_op_void,
++ .check_hw = efx_port_dummy_op_int,
++ .fini = efx_port_dummy_op_void,
++ .clear_interrupt = efx_port_dummy_op_void,
++ .reset_xaui = efx_port_dummy_op_void,
++};
++
++/* Dummy board operations */
++static int efx_nic_dummy_op_int(struct efx_nic *nic)
++{
++ return 0;
++}
++
++static void efx_nic_dummy_op_void(struct efx_nic *nic) {}
++
++static struct efx_board efx_dummy_board_info = {
++ .init = efx_nic_dummy_op_int,
++ .init_leds = efx_port_dummy_op_int,
++ .set_fault_led = efx_port_dummy_op_blink,
++ .monitor = efx_nic_dummy_op_int,
++ .blink = efx_port_dummy_op_blink,
++ .fini = efx_nic_dummy_op_void,
++};
++
++/**************************************************************************
++ *
++ * Data housekeeping
++ *
++ **************************************************************************/
++
++/* This zeroes out and then fills in the invariants in a struct
++ * efx_nic (including all sub-structures).
++ */
++static int efx_init_struct(struct efx_nic *efx, enum efx_type_index type,
++ struct pci_dev *pci_dev)
++{
++ struct efx_channel *channel;
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ int i, rc;
++
++ /* Initialise common structures */
++ memset(efx, 0, sizeof(*efx));
++ spin_lock_init(&efx->biu_lock);
++ spin_lock_init(&efx->phy_lock);
++ mutex_init(&efx->spi_lock);
++ sema_init(&efx->suspend_lock, 1);
++ INIT_WORK(&efx->reset_work, efx_reset_work);
++ INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor);
++ efx->pci_dev = pci_dev;
++ efx->state = STATE_INIT;
++ efx->reset_pending = RESET_TYPE_NONE;
++ strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
++ efx->board_info = efx_dummy_board_info;
++
++ efx->rx_checksum_enabled = 1;
++ spin_lock_init(&efx->netif_stop_lock);
++ spin_lock_init(&efx->stats_lock);
++ mutex_init(&efx->mac_lock);
++ efx->mac_op = &efx_dummy_mac_operations;
++ efx->phy_op = &efx_dummy_phy_operations;
++ INIT_LIST_HEAD(&efx->dl_node);
++ INIT_LIST_HEAD(&efx->dl_device_list);
++ efx->dl_cb = efx_default_callbacks;
++ INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work);
++ atomic_set(&efx->netif_stop_count, 1);
++
++ for (i = 0; i < EFX_MAX_CHANNELS; i++) {
++ channel = &efx->channel[i];
++ channel->efx = efx;
++ channel->channel = i;
++ channel->evqnum = i;
++ channel->work_pending = 0;
++ }
++ for (i = 0; i < EFX_MAX_TX_QUEUES; i++) {
++ tx_queue = &efx->tx_queue[i];
++ tx_queue->efx = efx;
++ tx_queue->queue = i;
++ tx_queue->buffer = NULL;
++ tx_queue->channel = &efx->channel[0]; /* for safety */
++ }
++ for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
++ rx_queue = &efx->rx_queue[i];
++ rx_queue->efx = efx;
++ rx_queue->queue = i;
++ rx_queue->channel = &efx->channel[0]; /* for safety */
++ rx_queue->buffer = NULL;
++ spin_lock_init(&rx_queue->add_lock);
++ INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work);
++ }
++
++ efx->type = efx_nic_types[type];
++
++ /* Sanity-check NIC type */
++ EFX_BUG_ON_PARANOID(efx->type->txd_ring_mask &
++ (efx->type->txd_ring_mask + 1));
++ EFX_BUG_ON_PARANOID(efx->type->rxd_ring_mask &
++ (efx->type->rxd_ring_mask + 1));
++ EFX_BUG_ON_PARANOID(efx->type->evq_size &
++ (efx->type->evq_size - 1));
++ /* As close as we can get to guaranteeing that we don't overflow */
++ EFX_BUG_ON_PARANOID(efx->type->evq_size <
++ (efx->type->txd_ring_mask + 1 +
++ efx->type->rxd_ring_mask + 1));
++
++ EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
++
++ /* Higher numbered interrupt modes are less capable! */
++ efx->interrupt_mode = max(efx->type->max_interrupt_mode,
++ interrupt_mode);
++#if defined(EFX_NEED_DUMMY_MSIX)
++ if (efx->interrupt_mode == EFX_INT_MODE_MSIX)
++ efx->interrupt_mode = EFX_INT_MODE_MSI;
++#endif
++
++ /* Tasks that can fail are last */
++ efx->refill_workqueue = create_workqueue("sfc_refill");
++ if (!efx->refill_workqueue) {
++ rc = -ENOMEM;
++ goto fail1;
++ }
++
++ efx->workqueue = create_singlethread_workqueue("sfc_work");
++ if (!efx->workqueue) {
++ rc = -ENOMEM;
++ goto fail2;
++ }
++
++#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
++ if (!efx->reset_workqueue) {
++ rc = -ENOMEM;
++ goto fail3;
++ }
++#endif
++
++ return 0;
++
++#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ fail3:
++ destroy_workqueue(efx->workqueue);
++ efx->workqueue = NULL;
++#endif
++
++ fail2:
++ destroy_workqueue(efx->refill_workqueue);
++ efx->refill_workqueue = NULL;
++ fail1:
++ return rc;
++}
++
++static void efx_fini_struct(struct efx_nic *efx)
++{
++#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ if (efx->reset_workqueue) {
++ destroy_workqueue(efx->reset_workqueue);
++ efx->reset_workqueue = NULL;
++ }
++#endif
++ if (efx->workqueue) {
++ destroy_workqueue(efx->workqueue);
++ efx->workqueue = NULL;
++ }
++ if (efx->refill_workqueue) {
++ destroy_workqueue(efx->refill_workqueue);
++ efx->refill_workqueue = NULL;
++ }
++}
++
++/**************************************************************************
++ *
++ * PCI interface
++ *
++ **************************************************************************/
++
++/* Main body of final NIC shutdown code
++ * This is called only at module unload (or hotplug removal).
++ */
++static void efx_pci_remove_main(struct efx_nic *efx)
++{
++ ASSERT_RTNL();
++
++ /* Skip everything if we never obtained a valid membase */
++ if (!efx->membase)
++ return;
++
++ efx_fini_channels(efx);
++ efx_fini_port(efx);
++
++ /* Shutdown the board, then the NIC and board state */
++ efx->board_info.fini(efx);
++ falcon_fini_nic(efx);
++ falcon_fini_interrupt(efx);
++ efx->board_info.fini(efx);
++
++ /* Tear down NAPI and LRO */
++ efx_fini_napi(efx);
++ efx_remove_all(efx);
++}
++
++/* Final NIC shutdown
++ * This is called only at module unload (or hotplug removal).
++ */
++static void efx_pci_remove(struct pci_dev *pci_dev)
++{
++ struct efx_nic *efx;
++
++ efx = pci_get_drvdata(pci_dev);
++ if (!efx)
++ return;
++
++ /* Unregister driver from driverlink layer */
++ efx_dl_unregister_nic(efx);
++
++ /* Mark the NIC as fini under both suspend_lock and
++ * rtnl_lock */
++ down(&efx->suspend_lock);
++ rtnl_lock();
++ efx->state = STATE_FINI;
++ up(&efx->suspend_lock);
++
++ if (efx->membase) {
++ /* Stop the NIC. Since we're in STATE_FINI, this
++ * won't be reversed. */
++ if (efx->net_dev_registered)
++ dev_close(efx->net_dev);
++
++ /* Release the rtnl lock. Any queued efx_resets()
++ * can now return early [we're in STATE_FINI]. */
++ rtnl_unlock();
++
++ efx_unregister_netdev(efx);
++ efx_fini_debugfs_channels(efx);
++
++ /* Wait for any scheduled resets to complete. No more will be
++ * scheduled from this point because efx_stop_all() has been
++ * called, we are no longer registered with driverlink, and
++ * the net_device's have been removed. */
++#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ flush_workqueue(efx->reset_workqueue);
++#else
++ flush_workqueue(efx->workqueue);
++#endif
++
++ /* Fini and remove all the software state */
++ rtnl_lock();
++ efx_pci_remove_main(efx);
++ }
++
++ rtnl_unlock();
++
++ efx_fini_io(efx);
++ EFX_LOG(efx, "shutdown successful\n");
++
++ pci_set_drvdata(pci_dev, NULL);
++ efx_fini_struct(efx);
++ kfree(efx);
++};
++
++/* Main body of NIC initialisation
++ * This is called at module load (or hotplug insertion, theoretically).
++ */
++static int efx_pci_probe_main(struct efx_nic *efx)
++{
++ int rc;
++
++ /* Do start-of-day initialisation */
++ rc = efx_probe_all(efx);
++ if (rc)
++ goto fail1;
++
++ /* Initialise port/channel net_dev's */
++ rc = efx_init_napi(efx);
++ if (rc)
++ goto fail2;
++
++ /* Initialise the board */
++ rc = efx->board_info.init(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to initialise board\n");
++ goto fail3;
++ }
++
++ /* Initialise device */
++ rc = falcon_init_nic(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to initialise NIC\n");
++ goto fail4;
++ }
++
++ /* Initialise port */
++ rc = efx_init_port(efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to initialise port\n");
++ goto fail5;
++ }
++
++ /* Initialise channels */
++ rc = efx_init_channels(efx);
++ if (rc)
++ goto fail6;
++
++ rc = falcon_init_interrupt(efx);
++ if (rc)
++ goto fail7;
++
++ /* Start up device - interrupts can occur from this point */
++ efx_start_all(efx);
++
++ /* Check basic functionality and set interrupt mode */
++ rc = efx_run_selftests(efx);
++ if (rc)
++ goto fail8;
++
++ /* Stop the NIC */
++ efx_stop_all(efx);
++
++ return 0;
++
++ fail8:
++ efx_stop_all(efx);
++ falcon_fini_interrupt(efx);
++ fail7:
++ efx_fini_channels(efx);
++ fail6:
++ efx_fini_port(efx);
++ fail5:
++ falcon_fini_nic(efx);
++ fail4:
++ efx->board_info.fini(efx);
++ fail3:
++ efx_fini_napi(efx);
++ fail2:
++ efx_remove_all(efx);
++ fail1:
++ return rc;
++}
++
++/* NIC initialisation
++ *
++ * This is called at module load (or hotplug insertion,
++ * theoretically). It sets up PCI mappings, tests and resets the NIC,
++ * sets up and registers the network devices with the kernel and hooks
++ * the interrupt service routine. It does not prepare the device for
++ * transmission; this is left to the first time one of the network
++ * interfaces is brought up (i.e. efx_net_open).
++ */
++static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
++ const struct pci_device_id *entry)
++{
++ struct efx_nic *efx;
++ enum efx_type_index type = entry->driver_data;
++ int i, rc;
++
++ /* Allocate and initialise a struct efx_nic */
++ efx = kmalloc(sizeof(*efx), GFP_KERNEL);
++ if (!efx) {
++ rc = -ENOMEM;
++ goto fail1;
++ }
++ pci_set_drvdata(pci_dev, efx);
++ rc = efx_init_struct(efx, type, pci_dev);
++ if (rc)
++ goto fail2;
++
++ EFX_INFO(efx, "Solarflare Communications NIC detected\n");
++
++ /* Set up basic I/O (BAR mappings etc) */
++ rc = efx_init_io(efx);
++ if (rc)
++ goto fail3;
++
++ /* From this point on we begin to expose the driver to the OS
++ * to varying degrees, so lets grab the suspend_lock and
++ * rtnl_lock to serialise against efx_reset() and
++ * friends. efx->state is not STATE_RUNNING yet, but we don't
++ * want these tasks to fail, just to block until we drop the
++ * lock
++ */
++ rc = down_interruptible(&efx->suspend_lock);
++ if (rc) {
++ EFX_ERR(efx, "suspend interrupted - aborting\n");
++ goto fail4;
++ }
++
++ rtnl_lock();
++
++ /* Probe, initialise and start everything. Run self-test */
++ for (i = 0; i < 5; i++) {
++ rc = efx_pci_probe_main(efx);
++ if (rc == 0)
++ break;
++
++ /* Retry if a recoverably reset event has been scheduled */
++ if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
++ (efx->reset_pending != RESET_TYPE_ALL))
++ goto fail5;
++
++ /* Serialise against efx_reset(). No more resets will be
++ * scheduled since efx_stop_all() has been called, and we
++ * have not and never have been registered with either
++ * the rtnetlink or driverlink layers. */
++ rtnl_unlock();
++ up(&efx->suspend_lock);
++
++#if defined(EFX_USE_CANCEL_WORK_SYNC)
++ cancel_work_sync(&efx->reset_work);
++#else
++ flush_workqueue(efx->reset_workqueue);
++#endif
++
++ down(&efx->suspend_lock);
++ rtnl_lock();
++
++ efx->reset_pending = RESET_TYPE_NONE;
++ };
++ if (rc) {
++ EFX_ERR(efx, "Could not reset NIC\n");
++ goto fail5;
++ }
++
++ /* Self-tests have all passed */
++ rc = efx_init_debugfs_channels(efx);
++ if (rc)
++ goto fail6;
++
++ /* Switch to the running state before we expose the device to
++ * the OS. This is to ensure that the initial gathering of
++ * MAC stats succeeds. */
++ efx->state = STATE_RUNNING;
++
++ rtnl_unlock();
++
++ rc = efx_register_netdev(efx);
++ if (rc)
++ goto fail7;
++
++ up(&efx->suspend_lock);
++
++ EFX_LOG(efx, "initialisation successful\n");
++
++ /* Register with driverlink layer */
++ rc = efx_dl_register_nic(efx);
++ if (rc)
++ goto fail8;
++
++ return 0;
++
++ fail8:
++ down(&efx->suspend_lock);
++ efx_unregister_netdev(efx);
++ fail7:
++ /* Re-acquire the rtnl lock around pci_remove_main() */
++ rtnl_lock();
++ efx_fini_debugfs_channels(efx);
++ fail6:
++ efx_pci_remove_main(efx);
++ fail5:
++ /* Drop the locks before fini */
++ rtnl_unlock();
++ up(&efx->suspend_lock);
++ fail4:
++ efx_fini_io(efx);
++ fail3:
++ efx_fini_struct(efx);
++ fail2:
++ kfree(efx);
++ fail1:
++ EFX_LOG(efx, "initialisation failed. rc=%d\n", rc);
++ return rc;
++}
++
++/* PCI driver definition */
++static struct pci_driver efx_pci_driver = {
++ .name = EFX_DRIVER_NAME,
++ .id_table = efx_pci_table,
++ .probe = efx_pci_probe,
++ .remove = efx_pci_remove,
++};
++
++/**************************************************************************
++ *
++ * Kernel module interface
++ *
++ *************************************************************************/
++
++module_param(interrupt_mode, uint, 0444);
++MODULE_PARM_DESC(interrupt_mode,
++ "Interrupt mode (0=>MSIX 1=>MSI 2=>legacy)");
++
++module_param(onload_offline_selftest, uint, 0444);
++MODULE_PARM_DESC(onload_offline_selftest, "Perform offline selftest on load");
++
++static int __init efx_init_module(void)
++{
++ int rc;
++
++ printk(KERN_INFO "Solarflare NET driver v" EFX_DRIVER_VERSION "\n");
++
++ rc = efx_init_debugfs();
++ if (rc)
++ goto err_debugfs;
++
++ rc = register_netdevice_notifier(&efx_netdev_notifier);
++ if (rc)
++ goto err_notifier;
++
++ rc = pci_register_driver(&efx_pci_driver);
++ if (rc < 0)
++ goto err_pci;
++
++ return 0;
++
++ err_pci:
++ unregister_netdevice_notifier(&efx_netdev_notifier);
++ err_notifier:
++ efx_fini_debugfs();
++ err_debugfs:
++ return rc;
++}
++
++static void __exit efx_exit_module(void)
++{
++ printk(KERN_INFO "Solarflare NET driver unloading\n");
++
++ pci_unregister_driver(&efx_pci_driver);
++ unregister_netdevice_notifier(&efx_netdev_notifier);
++ efx_fini_debugfs();
++
++}
++
++module_init(efx_init_module);
++module_exit(efx_exit_module);
++
++MODULE_AUTHOR("Michael Brown <mbrown@fensystems.co.uk> and "
++ "Solarflare Communications");
++MODULE_DESCRIPTION("Solarflare Communications network driver");
++MODULE_LICENSE("GPL");
++MODULE_DEVICE_TABLE(pci, efx_pci_table);
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/efx.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/efx.h
+--- linux-2.6.18.8/drivers/net/sfc/efx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/efx.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,103 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_EFX_H
++#define EFX_EFX_H
++
++#include "net_driver.h"
++
++/* PCI IDs */
++#define EFX_VENDID_SFC 0x1924
++#define FALCON_A_P_DEVID 0x0703
++#define FALCON_A_S_DEVID 0x6703
++#define FALCON_B_P_DEVID 0x0710
++
++/* TX */
++extern int efx_xmit(struct efx_nic *efx,
++ struct efx_tx_queue *tx_queue, struct sk_buff *skb);
++extern void efx_stop_queue(struct efx_nic *efx);
++extern void efx_wake_queue(struct efx_nic *efx);
++
++/* RX */
++#if defined(EFX_USE_FASTCALL)
++extern void fastcall efx_xmit_done(struct efx_tx_queue *tx_queue,
++ unsigned int index);
++#else
++extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
++#endif
++#if defined(EFX_USE_FASTCALL)
++extern void fastcall efx_rx_packet(struct efx_rx_queue *rx_queue,
++ unsigned int index, unsigned int len,
++ int checksummed, int discard);
++#else
++extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
++ unsigned int len, int checksummed, int discard);
++#endif
++extern void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf);
++
++/* Channels */
++extern void efx_process_channel_now(struct efx_channel *channel);
++extern int efx_flush_queues(struct efx_nic *efx);
++
++/* Ports */
++extern void efx_reconfigure_port(struct efx_nic *efx,
++ int on_disabled);
++
++/* Global */
++extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
++extern void efx_suspend(struct efx_nic *efx);
++extern void efx_resume(struct efx_nic *efx);
++extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs,
++ int rx_usecs);
++extern int efx_request_power(struct efx_nic *efx, int mw, const char *name);
++extern void efx_hex_dump(const u8 *, unsigned int, const char *);
++
++/* Dummy PHY ops for PHY drivers */
++extern int efx_port_dummy_op_int(struct efx_nic *efx);
++extern void efx_port_dummy_op_void(struct efx_nic *efx);
++extern void efx_port_dummy_op_blink(struct efx_nic *efx, int blink);
++
++
++extern unsigned int efx_monitor_interval;
++
++static inline void efx_schedule_channel(struct efx_channel *channel)
++{
++ EFX_TRACE(channel->efx, "channel %d scheduling NAPI poll on CPU%d\n",
++ channel->channel, raw_smp_processor_id());
++ channel->work_pending = 1;
++
++#if defined(EFX_HAVE_OLD_NAPI)
++ if (!test_and_set_bit(__LINK_STATE_RX_SCHED, &channel->napi_dev->state))
++ __netif_rx_schedule(channel->napi_dev);
++#else
++ netif_rx_schedule(channel->napi_dev, &channel->napi_str);
++#endif
++}
++
++
++#endif /* EFX_EFX_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/enum.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/enum.h
+--- linux-2.6.18.8/drivers/net/sfc/enum.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/enum.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,117 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_ENUM_H
++#define EFX_ENUM_H
++
++/**
++ * enum efx_loopback_mode - loopback modes
++ * @LOOPBACK_NONE: no loopback
++ * @LOOPBACK_NEAR: loopback nearest to bus
++ * @LOOPBACK_MAC: loopback within MAC unspecified level
++ * @LOOPBACK_XGMII: loopback within MAC at XGMII level
++ * @LOOPBACK_XGXS: loopback within MAC at XGXS level
++ * @LOOPBACK_XAUI: loopback within MAC at XAUI level
++ * @LOOPBACK_PHY: loopback within PHY unspecified level
++ * @LOOPBACK_PHYXS: loopback within PHY at PHYXS level
++ * @LOOPBACK_PCS: loopback within PHY at PCS level
++ * @LOOPBACK_PMAPMD: loopback within PHY at PMAPMD level
++ * @LOOPBACK_FAR: loopback furthest from bus
++ * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!)
++ */
++/* Please keep in order and up-to-date w.r.t the following two #defines */
++enum efx_loopback_mode {
++ LOOPBACK_NONE = 0,
++ LOOPBACK_NEAR = 1,
++ LOOPBACK_MAC = 2,
++ LOOPBACK_XGMII = 3,
++ LOOPBACK_XGXS = 4,
++ LOOPBACK_XAUI = 5,
++ LOOPBACK_PHY = 6,
++ LOOPBACK_PHYXS = 7,
++ LOOPBACK_PCS = 8,
++ LOOPBACK_PMAPMD = 9,
++ LOOPBACK_FAR = 10,
++ LOOPBACK_NETWORK = 11,
++ LOOPBACK_MAX
++};
++#define LOOPBACK_TEST_MAX LOOPBACK_FAR
++
++/* These loopbacks occur within the controller */
++#define LOOPBACKS_10G_INTERNAL ((1 << LOOPBACK_XGMII)| \
++ (1 << LOOPBACK_XGXS) | \
++ (1 << LOOPBACK_XAUI))
++
++#define LOOPBACKS_1G_INTERNAL (1 << LOOPBACK_MAC)
++
++#define LOOPBACK_MASK(_efx) \
++ (1 << (_efx)->loopback_mode)
++
++#define LOOPBACK_INTERNAL(_efx) \
++ (((LOOPBACKS_10G_INTERNAL | LOOPBACKS_1G_INTERNAL) & \
++ LOOPBACK_MASK(_efx)) ? 1 : 0)
++
++#define LOOPBACK_CHANGED(_from, _to, _mask) \
++ ((LOOPBACK_MASK(_from) ^ LOOPBACK_MASK(_to)) & \
++ (_mask) ? 1 : 0)
++
++#define LOOPBACK_OUT_OF(_from, _to, _mask) \
++ (((LOOPBACK_MASK(_from) & (_mask)) && \
++ ((LOOPBACK_MASK(_to) & (_mask)) == 0)) ? 1 : 0)
++
++/*****************************************************************************/
++
++/**
++ * enum reset_type - reset types
++ *
++ * %RESET_TYPE_INVSIBLE, %RESET_TYPE_ALL, %RESET_TYPE_WORLD and
++ * %RESET_TYPE_DISABLE specify the method/scope of the reset. The
++ * other valuesspecify reasons, which efx_schedule_reset() will choose
++ * a method for.
++ *
++ * @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts
++ * @RESET_TYPE_ALL: reset everything but PCI core blocks
++ * @RESET_TYPE_WORLD: reset everything, save & restore PCI config
++ * @RESET_TYPE_DISABLE: disable NIC
++ * @RESET_TYPE_MONITOR: reset due to hardware monitor
++ * @RESET_TYPE_INT_ERROR: reset due to internal error
++ * @RESET_TYPE_RX_RECOVERY: reset to recover from RX datapath errors
++ */
++enum reset_type {
++ RESET_TYPE_NONE = -1,
++ RESET_TYPE_INVISIBLE = 0,
++ RESET_TYPE_ALL = 1,
++ RESET_TYPE_WORLD = 2,
++ RESET_TYPE_DISABLE = 3,
++ RESET_TYPE_MAX_METHOD,
++ RESET_TYPE_MONITOR,
++ RESET_TYPE_INT_ERROR,
++ RESET_TYPE_RX_RECOVERY,
++ RESET_TYPE_RX_DESC_FETCH,
++ RESET_TYPE_TX_DESC_FETCH,
++ RESET_TYPE_MAX,
++};
++
++#endif /* EFX_ENUM_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/ethtool.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/ethtool.c
+--- linux-2.6.18.8/drivers/net/sfc/ethtool.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/ethtool.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,734 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/netdevice.h>
++#include <linux/ethtool.h>
++#include <linux/rtnetlink.h>
++#include <asm/uaccess.h>
++#include "net_driver.h"
++#include "selftest.h"
++#include "efx.h"
++#include "ethtool.h"
++#include "falcon.h"
++#include "gmii.h"
++
++static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable);
++
++struct ethtool_string {
++ char name[ETH_GSTRING_LEN];
++};
++
++struct efx_ethtool_stat {
++ const char *name;
++ enum {
++ EFX_ETHTOOL_STAT_SOURCE_mac_stats,
++ EFX_ETHTOOL_STAT_SOURCE_nic,
++ EFX_ETHTOOL_STAT_SOURCE_channel
++ } source;
++ unsigned offset;
++ u64(*get_stat) (void *field); /* Reader function */
++};
++
++/* Initialiser for a struct #efx_ethtool_stat with type-checking */
++#define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \
++ get_stat_function) { \
++ .name = #stat_name, \
++ .source = EFX_ETHTOOL_STAT_SOURCE_##source_name, \
++ .offset = ((((field_type *) 0) == \
++ &((struct efx_##source_name *)0)->field) ? \
++ offsetof(struct efx_##source_name, field) : \
++ offsetof(struct efx_##source_name, field)), \
++ .get_stat = get_stat_function, \
++}
++
++static u64 efx_get_uint_stat(void *field)
++{
++ return *(unsigned int *)field;
++}
++
++static u64 efx_get_ulong_stat(void *field)
++{
++ return *(unsigned long *)field;
++}
++
++static u64 efx_get_u64_stat(void *field)
++{
++ return *(u64 *) field;
++}
++
++static u64 efx_get_atomic_stat(void *field)
++{
++ return atomic_read((atomic_t *) field);
++}
++
++#define EFX_ETHTOOL_ULONG_MAC_STAT(field) \
++ EFX_ETHTOOL_STAT(field, mac_stats, field, \
++ unsigned long, efx_get_ulong_stat)
++
++#define EFX_ETHTOOL_U64_MAC_STAT(field) \
++ EFX_ETHTOOL_STAT(field, mac_stats, field, \
++ u64, efx_get_u64_stat)
++
++#define EFX_ETHTOOL_UINT_NIC_STAT(name) \
++ EFX_ETHTOOL_STAT(name, nic, n_##name, \
++ unsigned int, efx_get_uint_stat)
++
++#define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \
++ EFX_ETHTOOL_STAT(field, nic, errors.field, \
++ atomic_t, efx_get_atomic_stat)
++
++#define EFX_ETHTOOL_UINT_CHANNEL_STAT(field) \
++ EFX_ETHTOOL_STAT(field, channel, n_##field, \
++ unsigned int, efx_get_uint_stat)
++
++static struct efx_ethtool_stat efx_ethtool_stats[] = {
++ EFX_ETHTOOL_U64_MAC_STAT(tx_bytes),
++ EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes),
++ EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_packets),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_bad),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_pause),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_control),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_unicast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_multicast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_broadcast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_lt64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_65_to_127),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_128_to_255),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_256_to_511),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_512_to_1023),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_1024_to_15xx),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_15xx_to_jumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_gtjumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_single_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_multiple_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_deferred),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_late_collision),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_deferred),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error),
++ EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error),
++ EFX_ETHTOOL_U64_MAC_STAT(rx_bytes),
++ EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes),
++ EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_packets),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_good),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_pause),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_control),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_unicast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_multicast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_broadcast),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_lt64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_65_to_127),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_128_to_255),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_256_to_511),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_512_to_1023),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_1024_to_15xx),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_15xx_to_jumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_gtjumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_lt64),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_64_to_15xx),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_15xx_to_jumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_gtjumbo),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_overflow),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_missed),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_false_carrier),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_symbol_error),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_align_error),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_length_error),
++ EFX_ETHTOOL_ULONG_MAC_STAT(rx_internal_error),
++ EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt),
++ EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
++ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
++ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
++ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
++ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
++};
++
++/* Number of ethtool statistics */
++#define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats)
++
++/**************************************************************************
++ *
++ * Ethtool operations
++ *
++ **************************************************************************
++ */
++
++/* Identify device by flashing LEDs */
++static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ efx->board_info.blink(efx, 1);
++ schedule_timeout_interruptible(seconds * HZ);
++ efx->board_info.blink(efx, 0);
++ return 0;
++}
++
++/* This must be called with rtnl_lock held. */
++int efx_ethtool_get_settings(struct net_device *net_dev,
++ struct ethtool_cmd *ecmd)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ return efx->mac_op->get_settings(efx, ecmd);
++}
++
++/* This must be called with rtnl_lock held. */
++int efx_ethtool_set_settings(struct net_device *net_dev,
++ struct ethtool_cmd *ecmd)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc;
++
++ rc = efx->mac_op->set_settings(efx, ecmd);
++ if (rc)
++ return rc;
++
++ /* Push the settings to the MAC */
++ efx_reconfigure_port(efx, 0);
++
++ return 0;
++}
++
++static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
++ struct ethtool_drvinfo *info)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver));
++ strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
++ strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
++}
++
++/**
++ * efx_fill_test - fill in an individual self-test entry
++ * @test_index: Index of the test
++ * @strings: Ethtool strings, or %NULL
++ * @data: Ethtool test results, or %NULL
++ * @test: Pointer to test result (used only if data != %NULL)
++ * @unit_format: Unit name format (e.g. "channel\%d")
++ * @unit_id: Unit id (e.g. 0 for "channel0")
++ * @test_format: Test name format (e.g. "loopback.\%s.tx.sent")
++ * @test_id: Test id (e.g. "PHY" for "loopback.PHY.tx_sent")
++ *
++ * Fill in an individual self-test entry.
++ */
++static void efx_fill_test(unsigned int test_index,
++ struct ethtool_string *strings, u64 *data,
++ int *test, const char *unit_format, int unit_id,
++ const char *test_format, const char *test_id)
++{
++ struct ethtool_string unit_str, test_str;
++
++ /* Fill data value, if applicable */
++ if (data)
++ data[test_index] = *test;
++
++ /* Fill string, if applicable */
++ if (strings) {
++ snprintf(unit_str.name, sizeof(unit_str.name),
++ unit_format, unit_id);
++ snprintf(test_str.name, sizeof(test_str.name),
++ test_format, test_id);
++ snprintf(strings[test_index].name,
++ sizeof(strings[test_index].name),
++ "%-9s%-17s", unit_str.name, test_str.name);
++ }
++}
++
++#define EFX_PORT_NAME "port%d", 0
++
++/**
++ * efx_fill_loopback_test - fill in a block of loopback self-test entries
++ * @efx: Efx NIC
++ * @lb_tests: Efx loopback self-test results structure
++ * @mode: Loopback test mode
++ * @test_index: Starting index of the test
++ * @strings: Ethtool strings, or %NULL
++ * @data: Ethtool test results, or %NULL
++ *
++ * Fill in a block of loopback self-test entries. Return new test
++ * index.
++ */
++static int efx_fill_loopback_test(struct efx_nic *efx,
++ struct efx_loopback_self_tests *lb_tests,
++ enum efx_loopback_mode mode,
++ unsigned int test_index,
++ struct ethtool_string *strings, u64 *data)
++{
++ struct efx_tx_queue *tx_queue;
++
++ efx_for_each_tx_queue(tx_queue, efx) {
++ efx_fill_test(test_index++, strings, data,
++ &lb_tests->tx_sent[tx_queue->queue],
++ EFX_TX_QUEUE_NAME(tx_queue),
++ "loopback.%s.tx_sent",
++ efx_loopback_mode_names[mode]);
++ efx_fill_test(test_index++, strings, data,
++ &lb_tests->tx_done[tx_queue->queue],
++ EFX_TX_QUEUE_NAME(tx_queue),
++ "loopback.%s.tx_done",
++ efx_loopback_mode_names[mode]);
++ }
++ efx_fill_test(test_index++, strings, data,
++ &lb_tests->rx_good,
++ EFX_PORT_NAME,
++ "loopback.%s.rx_good",
++ efx_loopback_mode_names[mode]);
++ efx_fill_test(test_index++, strings, data,
++ &lb_tests->rx_bad,
++ EFX_PORT_NAME,
++ "loopback.%s.rx_bad",
++ efx_loopback_mode_names[mode]);
++
++ return test_index;
++}
++
++/**
++ * efx_ethtool_fill_self_tests - get self-test details
++ * @efx: Efx NIC
++ * @tests: Efx self-test results structure, or %NULL
++ * @strings: Ethtool strings, or %NULL
++ * @data: Ethtool test results, or %NULL
++ *
++ * Get self-test number of strings, strings, and/or test results.
++ * Return number of strings (== number of test results).
++ *
++ * The reason for merging these three functions is to make sure that
++ * they can never be inconsistent.
++ */
++static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
++ struct efx_self_tests *tests,
++ struct ethtool_string *strings,
++ u64 *data)
++{
++ struct efx_channel *channel;
++ unsigned int n = 0;
++ enum efx_loopback_mode mode;
++
++ /* Interrupt */
++ efx_fill_test(n++, strings, data, &tests->interrupt,
++ "core", 0, "interrupt", NULL);
++
++ /* Event queues */
++ efx_for_each_channel(channel, efx) {
++ efx_fill_test(n++, strings, data,
++ &tests->eventq_dma[channel->channel],
++ EFX_CHANNEL_NAME(channel),
++ "eventq.dma", NULL);
++ efx_fill_test(n++, strings, data,
++ &tests->eventq_int[channel->channel],
++ EFX_CHANNEL_NAME(channel),
++ "eventq.int", NULL);
++ efx_fill_test(n++, strings, data,
++ &tests->eventq_poll[channel->channel],
++ EFX_CHANNEL_NAME(channel),
++ "eventq.poll", NULL);
++ }
++
++ /* PHY presence */
++ efx_fill_test(n++, strings, data, &tests->phy_ok,
++ EFX_PORT_NAME, "phy_ok", NULL);
++
++ /* Loopback tests */
++ efx_fill_test(n++, strings, data, &tests->loopback_speed,
++ EFX_PORT_NAME, "loopback.speed", NULL);
++ efx_fill_test(n++, strings, data, &tests->loopback_full_duplex,
++ EFX_PORT_NAME, "loopback.full_duplex", NULL);
++ for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) {
++ if (!(efx->loopback_modes & (1 << mode)))
++ continue;
++ n = efx_fill_loopback_test(efx,
++ &tests->loopback[mode], mode, n,
++ strings, data);
++ }
++
++ return n;
++}
++
++static int efx_ethtool_get_stats_count(struct net_device *net_dev)
++{
++ return EFX_ETHTOOL_NUM_STATS;
++}
++
++static int efx_ethtool_self_test_count(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
++}
++
++static void efx_ethtool_get_strings(struct net_device *net_dev,
++ u32 string_set, u8 *strings)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct ethtool_string *ethtool_strings =
++ (struct ethtool_string *)strings;
++ int i;
++
++ switch (string_set) {
++ case ETH_SS_STATS:
++ for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++)
++ strncpy(ethtool_strings[i].name,
++ efx_ethtool_stats[i].name,
++ sizeof(ethtool_strings[i].name));
++ break;
++ case ETH_SS_TEST:
++ efx_ethtool_fill_self_tests(efx, NULL,
++ ethtool_strings, NULL);
++ break;
++ default:
++ /* No other string sets */
++ break;
++ }
++}
++
++static void efx_ethtool_get_stats(struct net_device *net_dev,
++ struct ethtool_stats *stats
++ __attribute__ ((unused)), u64 *data)
++{
++ unsigned long flags __attribute__ ((unused));
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_mac_stats *mac_stats = &efx->mac_stats;
++ struct efx_ethtool_stat *stat;
++ struct efx_channel *channel;
++ int i;
++
++ EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS);
++
++ /* Update MAC and NIC statistics */
++ net_dev->get_stats(net_dev);
++ falcon_update_nic_stats(efx);
++
++ /* Fill detailed statistics buffer */
++ for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) {
++ stat = &efx_ethtool_stats[i];
++ switch (stat->source) {
++ case EFX_ETHTOOL_STAT_SOURCE_mac_stats:
++ data[i] = stat->get_stat((void *)mac_stats +
++ stat->offset);
++ break;
++ case EFX_ETHTOOL_STAT_SOURCE_nic:
++ data[i] = stat->get_stat((void *)efx + stat->offset);
++ break;
++ case EFX_ETHTOOL_STAT_SOURCE_channel:
++ data[i] = 0;
++ efx_for_each_channel(channel, efx)
++ data[i] += stat->get_stat((void *)channel +
++ stat->offset);
++ break;
++ }
++ }
++}
++
++static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
++{
++ struct efx_nic *efx = net_dev->priv;
++ int rc;
++
++ rc = ethtool_op_set_tx_csum(net_dev, enable);
++ if (rc)
++ return rc;
++
++
++ efx_flush_queues(efx);
++
++ return 0;
++}
++
++static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ /* No way to stop the hardware doing the checks; we just
++ * ignore the result.
++ */
++ efx->rx_checksum_enabled = (enable ? 1 : 0);
++
++ return 0;
++}
++
++static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ return efx->rx_checksum_enabled;
++}
++
++static void efx_ethtool_self_test(struct net_device *net_dev,
++ struct ethtool_test *test, u64 *data)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_self_tests efx_tests;
++ int offline, already_up;
++ int rc;
++
++ /* Make sure we've got rtnl lock since we're playing with
++ * interrupts, and calling efx_process_channel_now and others
++ */
++ ASSERT_RTNL();
++
++ /* If the NIC isn't in the RUNNING state then exit */
++ if (efx->state != STATE_RUNNING) {
++ rc = -EIO;
++ goto fail1;
++ }
++
++ /* Make sure the interface is up. We need interrupts, NAPI
++ * and some RX buffers so this is helpful. NB. The caller has
++ * rtnl_lock so nobody else can call dev_open. */
++ already_up = (efx->net_dev->flags & IFF_UP);
++ if (!already_up) {
++ rc = dev_open(efx->net_dev);
++ if (rc) {
++ EFX_ERR(efx, "failed opening device.\n");
++ goto fail2;
++ }
++ }
++
++ memset(&efx_tests, 0, sizeof(efx_tests));
++ offline = (test->flags & ETH_TEST_FL_OFFLINE);
++
++ /* Perform online self tests first */
++ rc = efx_online_test(efx, &efx_tests);
++ if (rc)
++ goto out;
++
++ /* Perform offline tests only if online tests passed */
++ if (offline) {
++ /* Stop the kernel from sending packets during the test. The
++ * selftest will be consistently bringing the port up and down
++ * as it moves between loopback modes, so the watchdog timer
++ * probably won't run anyway */
++ efx_stop_queue(efx);
++
++ rc = efx_flush_queues(efx);
++ if (rc != 0)
++ goto out_offline;
++
++ rc = efx_offline_test(efx, &efx_tests,
++ efx->loopback_modes);
++ out_offline:
++ efx_wake_queue(efx);
++ }
++
++ /* fall-thru */
++ out:
++ if (!already_up)
++ dev_close(efx->net_dev);
++
++ EFX_LOG(efx, "%s all %sline self-tests\n",
++ rc == 0 ? "passed" : "failed", offline ? "off" : "on");
++
++ fail2:
++ fail1:
++ /* Fill ethtool results structures */
++ efx_ethtool_fill_self_tests(efx, &efx_tests, NULL, data);
++ if (rc)
++ test->flags |= ETH_TEST_FL_FAILED;
++}
++
++/* Restart autonegotiation */
++static int efx_ethtool_nway_reset(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ return mii_nway_restart(&efx->mii);
++}
++
++static u32 efx_ethtool_get_link(struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ return efx->link_up;
++}
++
++static int efx_ethtool_get_coalesce(struct net_device *net_dev,
++ struct ethtool_coalesce *coalesce)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_tx_queue *tx_queue;
++ struct efx_rx_queue *rx_queue;
++ struct efx_channel *channel;
++
++ memset(coalesce, 0, sizeof(*coalesce));
++
++ /* Find lowest IRQ moderation across all used TX queues */
++ coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
++ efx_for_each_tx_queue(tx_queue, efx) {
++ channel = tx_queue->channel;
++ if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
++ if (channel->used_flags != EFX_USED_BY_RX_TX)
++ coalesce->tx_coalesce_usecs_irq =
++ channel->irq_moderation;
++ else
++ coalesce->tx_coalesce_usecs_irq = 0;
++ }
++ }
++
++ /* Find lowest IRQ moderation across all used RX queues */
++ coalesce->rx_coalesce_usecs_irq = ~((u32) 0);
++ efx_for_each_rx_queue(rx_queue, efx) {
++ channel = rx_queue->channel;
++ if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq)
++ coalesce->rx_coalesce_usecs_irq =
++ channel->irq_moderation;
++ }
++
++ return 0;
++}
++
++/* Set coalescing parameters
++ * The difficulties occur for shared channels
++ */
++static int efx_ethtool_set_coalesce(struct net_device *net_dev,
++ struct ethtool_coalesce *coalesce)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_channel *channel;
++ struct efx_tx_queue *tx_queue;
++ unsigned tx_usecs, rx_usecs;
++
++ if (coalesce->use_adaptive_rx_coalesce ||
++ coalesce->use_adaptive_tx_coalesce)
++ return -EOPNOTSUPP;
++
++ if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) {
++ EFX_ERR(efx, "invalid coalescing setting. "
++ "Only rx/tx_coalesce_usecs_irq are supported\n");
++ return -EOPNOTSUPP;
++ }
++
++ rx_usecs = coalesce->rx_coalesce_usecs_irq;
++ tx_usecs = coalesce->tx_coalesce_usecs_irq;
++
++ /* If the channel is shared only allow RX parameters to be set */
++ efx_for_each_tx_queue(tx_queue, efx) {
++ if ((tx_queue->channel->used_flags == EFX_USED_BY_RX_TX) &&
++ tx_usecs) {
++ EFX_ERR(efx, "Channel is shared. "
++ "Only RX coalescing may be set\n");
++ return -EOPNOTSUPP;
++ }
++ }
++
++ efx_init_irq_moderation(efx, tx_usecs, rx_usecs);
++
++ /* Reset channel to pick up new moderation value. Note that
++ * this may change the value of the irq_moderation field
++ * (e.g. to allow for hardware timer granularity).
++ */
++ efx_for_each_channel(channel, efx)
++ falcon_set_int_moderation(channel);
++
++ return 0;
++}
++
++static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
++ struct ethtool_pauseparam *pause)
++{
++ struct efx_nic *efx = net_dev->priv;
++ enum efx_fc_type flow_control = efx->flow_control;
++ int rc;
++
++ flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO);
++ flow_control |= pause->rx_pause ? EFX_FC_RX : 0;
++ flow_control |= pause->tx_pause ? EFX_FC_TX : 0;
++ flow_control |= pause->autoneg ? EFX_FC_AUTO : 0;
++
++ /* Try to push the pause parameters */
++ rc = efx->mac_op->set_pause(efx, flow_control);
++ if (rc)
++ return rc;
++
++ /* Push the settings to the MAC */
++ efx_reconfigure_port(efx, 0);
++
++ return 0;
++}
++
++static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
++ struct ethtool_pauseparam *pause)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ pause->rx_pause = (efx->flow_control & EFX_FC_RX) ? 1 : 0;
++ pause->tx_pause = (efx->flow_control & EFX_FC_TX) ? 1 : 0;
++ pause->autoneg = (efx->flow_control & EFX_FC_AUTO) ? 1 : 0;
++}
++
++
++#if defined(EFX_USE_ETHTOOL_GET_PERM_ADDR)
++static int efx_ethtool_op_get_perm_addr(struct net_device *net_dev,
++ struct ethtool_perm_addr *addr,
++ u8 *data)
++{
++ struct efx_nic *efx = net_dev->priv;
++
++ memcpy(data, efx->mac_address, ETH_ALEN);
++
++ return 0;
++}
++#endif
++
++struct ethtool_ops efx_ethtool_ops = {
++ .get_settings = efx_ethtool_get_settings,
++ .set_settings = efx_ethtool_set_settings,
++ .get_drvinfo = efx_ethtool_get_drvinfo,
++ .nway_reset = efx_ethtool_nway_reset,
++ .get_link = efx_ethtool_get_link,
++ .get_coalesce = efx_ethtool_get_coalesce,
++ .set_coalesce = efx_ethtool_set_coalesce,
++ .get_pauseparam = efx_ethtool_get_pauseparam,
++ .set_pauseparam = efx_ethtool_set_pauseparam,
++ .get_rx_csum = efx_ethtool_get_rx_csum,
++ .set_rx_csum = efx_ethtool_set_rx_csum,
++ .get_tx_csum = ethtool_op_get_tx_csum,
++ .set_tx_csum = efx_ethtool_set_tx_csum,
++ .get_sg = ethtool_op_get_sg,
++ .set_sg = ethtool_op_set_sg,
++#if defined(EFX_USE_ETHTOOL_FLAGS)
++ .get_flags = ethtool_op_get_flags,
++ .set_flags = ethtool_op_set_flags,
++#endif
++ .self_test_count = efx_ethtool_self_test_count,
++ .self_test = efx_ethtool_self_test,
++ .get_strings = efx_ethtool_get_strings,
++ .phys_id = efx_ethtool_phys_id,
++ .get_stats_count = efx_ethtool_get_stats_count,
++ .get_ethtool_stats = efx_ethtool_get_stats,
++#if defined(EFX_USE_ETHTOOL_GET_PERM_ADDR)
++ .get_perm_addr = efx_ethtool_op_get_perm_addr,
++#endif
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/ethtool.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/ethtool.h
+--- linux-2.6.18.8/drivers/net/sfc/ethtool.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/ethtool.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,44 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005: Fen Systems Ltd.
++ * Copyright 2006: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_ETHTOOL_H
++#define EFX_ETHTOOL_H
++
++#include "net_driver.h"
++
++/*
++ * Ethtool support
++ */
++
++extern int efx_ethtool_get_settings(struct net_device *net_dev,
++ struct ethtool_cmd *ecmd);
++extern int efx_ethtool_set_settings(struct net_device *net_dev,
++ struct ethtool_cmd *ecmd);
++
++extern struct ethtool_ops efx_ethtool_ops;
++
++#endif /* EFX_ETHTOOL_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/extraversion.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/extraversion.h
+--- linux-2.6.18.8/drivers/net/sfc/extraversion.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/extraversion.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,4 @@
++/*
++ * If compiling on kernels with backported features you may need to
++ * define EFX_DIST_KVER_ symbols here
++ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/falcon.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon.c
+--- linux-2.6.18.8/drivers/net/sfc/falcon.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,3708 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <asm/io.h>
++#include <asm/bitops.h>
++#include <linux/delay.h>
++#include <linux/pci.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include "net_driver.h"
++#include "bitfield.h"
++#include "efx.h"
++#include "mac.h"
++#include "gmii.h"
++#include "spi.h"
++#include "falcon.h"
++#include "falcon_hwdefs.h"
++#include "falcon_io.h"
++#include "mdio_10g.h"
++#include "phy.h"
++#include "boards.h"
++#include "driverlink.h"
++#include "workarounds.h"
++
++/* Falcon hardware control.
++ * Falcon is the internal codename for the SFC4000 controller that is
++ * present in SFE400X evaluation boards
++ */
++
++struct falcon_nic_data {
++ /* Number of entries in each TX queue descriptor cache. */
++ unsigned tx_dc_entries;
++ /* Number of entries in each RX queue descriptor cache. */
++ unsigned rx_dc_entries;
++ /* Base address in SRAM of TX queue descriptor caches. */
++ unsigned tx_dc_base;
++ /* Base address in SRAM of RX queue descriptor caches. */
++ unsigned rx_dc_base;
++
++ /* Previous loopback mode used in deconfigure_mac_wrapper */
++ enum efx_loopback_mode old_loopback_mode;
++
++ /* Driverlink parameters */
++ struct efx_dl_falcon_resources resources;
++};
++
++/**************************************************************************
++ *
++ * Configurable values
++ *
++ **************************************************************************
++ */
++
++static int disable_dma_stats;
++
++/* Specify the size of the RX descriptor cache */
++static int descriptor_cache_size = 64;
++
++/*
++ * Override EEPROM/flash type from non-volatile configuration or GPIO;
++ * may need to be specified if bootstrapping from blank flash.
++ */
++static unsigned int eeprom_type = -1;
++static unsigned int flash_type = -1;
++
++/* RX FIFO XOFF watermark
++ *
++ * When the amount of the RX FIFO increases used increases past this
++ * watermark send XOFF. Only used if RX flow control is enabled (ethtool -A)
++ * This also has an effect on RX/TX arbitration
++ */
++static int rx_xoff_thresh_bytes = -1;
++module_param(rx_xoff_thresh_bytes, int, 0644);
++MODULE_PARM_DESC(rx_xoff_thresh_bytes, "RX fifo XOFF threshold");
++
++/* RX FIFO XON watermark
++ *
++ * When the amount of the RX FIFO used decreases below this
++ * watermark send XON. Only used if TX flow control is enabled (ethtool -A)
++ * This also has an effect on RX/TX arbitration
++ */
++static int rx_xon_thresh_bytes = -1;
++module_param(rx_xon_thresh_bytes, int, 0644);
++MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
++
++/* TX descriptor ring size - min 512 max 4k */
++#define FALCON_TXD_RING_ORDER TX_DESCQ_SIZE_1K
++#define FALCON_TXD_RING_SIZE 1024
++#define FALCON_TXD_RING_MASK (FALCON_TXD_RING_SIZE - 1)
++
++/* RX descriptor ring size - min 512 max 4k */
++#define FALCON_RXD_RING_ORDER RX_DESCQ_SIZE_1K
++#define FALCON_RXD_RING_SIZE 1024
++#define FALCON_RXD_RING_MASK (FALCON_RXD_RING_SIZE - 1)
++
++/* Event queue size - max 32k */
++#define FALCON_EVQ_ORDER EVQ_SIZE_4K
++#define FALCON_EVQ_SIZE 4096
++#define FALCON_EVQ_MASK (FALCON_EVQ_SIZE - 1)
++
++/* Max number of internal errors. After this resets will not be performed */
++#define FALCON_MAX_INT_ERRORS 4
++
++/* Maximum period that we wait for flush events. If the flush event
++ * doesn't arrive in this period of time then we check if the queue
++ * was disabled anyway. */
++#define FALCON_FLUSH_TIMEOUT 10 /* 10ms */
++
++/**************************************************************************
++ *
++ * Falcon constants
++ *
++ **************************************************************************
++ */
++
++/* DMA address mask (up to 46-bit, avoiding compiler warnings)
++ *
++ * Note that it is possible to have a platform with 64-bit longs and
++ * 32-bit DMA addresses, or vice versa. EFX_DMA_MASK takes care of the
++ * platform DMA mask.
++ */
++#if BITS_PER_LONG == 64
++#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffUL)
++#else
++#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffULL)
++#endif
++
++/* TX DMA length mask (13-bit) */
++#define FALCON_TX_DMA_MASK (8192 - 1)
++
++/* Alignment of special buffers (4KB) */
++#define FALCON_BUF_ALIGN 4096
++
++/* Dummy SRAM size code */
++#define SRM_NB_BSZ_ONCHIP_ONLY (-1)
++
++/* Be nice if these (or equiv.) were in linux/pci_regs.h, but they're not. */
++#define PCI_EXP_DEVCAP_PWR_VAL_LBN (18)
++/* This field takes up bits 26 and 27. */
++#define PCI_EXP_DEVCAP_PWR_SCL_LBN (26)
++#define PCI_EXP_LNKSTA_LNK_WID (0x3f0)
++#define PCI_EXP_LNKSTA_LNK_WID_LBN (4)
++
++
++/**************************************************************************
++ *
++ * Falcon hardware access
++ *
++ **************************************************************************/
++
++/* Read the current event from the event queue */
++static inline efx_qword_t *falcon_event(struct efx_channel *channel,
++ unsigned int index)
++{
++ return (((efx_qword_t *) (channel->eventq.addr)) + index);
++}
++
++/* See if an event is present
++ *
++ * We check both the high and low dword of the event for all ones. We
++ * wrote all ones when we cleared the event, and no valid event can
++ * have all ones in either its high or low dwords. This approach is
++ * robust against reordering.
++ *
++ * Note that using a single 64-bit comparison is incorrect; even
++ * though the CPU read will be atomic, the DMA write may not be.
++ */
++static inline int falcon_event_present(efx_qword_t *event)
++{
++ return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
++ EFX_DWORD_IS_ALL_ONES(event->dword[1])));
++}
++
++/* Read dword from a Falcon PCIE core register */
++static void falcon_pcie_core_read_reg(struct efx_nic *efx, int address,
++ efx_dword_t *result)
++{
++ efx_oword_t temp;
++
++ BUG_ON(FALCON_REV(efx) < FALCON_REV_B0);
++ BUG_ON(address & 3 || address < 0);
++
++ EFX_POPULATE_OWORD_1(temp, PCIE_CORE_ADDR, address);
++
++ falcon_write(efx, &temp, PCIE_CORE_INDIRECT_REG);
++ falcon_read(efx, &temp, PCIE_CORE_INDIRECT_REG);
++ /* Extract PCIE_CORE_VALUE without byte-swapping */
++ BUILD_BUG_ON(PCIE_CORE_VALUE_LBN != 32 ||
++ PCIE_CORE_VALUE_WIDTH != 32);
++ result->u32[0] = temp.u32[1];
++}
++
++/* Write dword to a Falcon PCIE core register */
++static void falcon_pcie_core_write_reg(struct efx_nic *efx, int address,
++ efx_dword_t value)
++{
++ efx_oword_t temp;
++
++ BUG_ON(FALCON_REV(efx) < FALCON_REV_B0);
++ BUG_ON(address & 0x3 || address < 0);
++
++ EFX_POPULATE_OWORD_2(temp,
++ PCIE_CORE_ADDR, address,
++ PCIE_CORE_RW, 1);
++ /* Fill PCIE_CORE_VALUE without byte-swapping */
++ BUILD_BUG_ON(PCIE_CORE_VALUE_LBN != 32 ||
++ PCIE_CORE_VALUE_WIDTH != 32);
++ temp.u32[1] = value.u32[0];
++ falcon_write(efx, &temp, PCIE_CORE_INDIRECT_REG);
++}
++
++/**************************************************************************
++ *
++ * I2C bus - this is a bit-bashing interface using GPIO pins
++ * Note that it uses the output enables to tristate the outputs
++ * SDA is the data pin and SCL is the clock
++ *
++ **************************************************************************
++ */
++static void falcon_setsdascl(struct efx_i2c_interface *i2c)
++{
++ efx_oword_t reg;
++
++ falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
++ EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, (i2c->scl ? 0 : 1));
++ EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, (i2c->sda ? 0 : 1));
++ falcon_write(i2c->efx, &reg, GPIO_CTL_REG_KER);
++}
++
++static int falcon_getsda(struct efx_i2c_interface *i2c)
++{
++ efx_oword_t reg;
++
++ falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
++ return EFX_OWORD_FIELD(reg, GPIO3_IN);
++}
++
++static int falcon_getscl(struct efx_i2c_interface *i2c)
++{
++ efx_oword_t reg;
++
++ falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
++ return EFX_DWORD_FIELD(reg, GPIO0_IN);
++}
++
++static struct efx_i2c_bit_operations falcon_i2c_bit_operations = {
++ .setsda = falcon_setsdascl,
++ .setscl = falcon_setsdascl,
++ .getsda = falcon_getsda,
++ .getscl = falcon_getscl,
++ .udelay = 100,
++ .mdelay = 10,
++};
++
++/**************************************************************************
++ *
++ * Falcon special buffer handling
++ * Special buffers are used for event queues and the TX and RX
++ * descriptor rings.
++ *
++ *************************************************************************/
++
++/* Adds the relevant entries to the full-mode buffer table. */
++static int
++falcon_pin_special_buffer_full(struct efx_nic *efx,
++ struct efx_special_buffer *buffer)
++{
++ efx_qword_t buf_desc;
++ int index;
++ dma_addr_t dma_addr;
++ int i;
++
++ /* Write buffer descriptors to NIC */
++ for (i = 0; i < buffer->entries; i++) {
++ index = buffer->index + i;
++ dma_addr = buffer->dma_addr + (i * 4096);
++ EFX_LOG(efx, "mapping special buffer %d at %llx\n",
++ index, (unsigned long long)dma_addr);
++ EFX_POPULATE_QWORD_4(buf_desc,
++ IP_DAT_BUF_SIZE, IP_DAT_BUF_SIZE_4K,
++ BUF_ADR_REGION, 0,
++ BUF_ADR_FBUF, (dma_addr >> 12),
++ BUF_OWNER_ID_FBUF, 0);
++ falcon_write_sram(efx, &buf_desc, index);
++ }
++
++ return 0;
++}
++
++/* Clears the relevant entries from the buffer table */
++static void
++falcon_clear_special_buffer_full(struct efx_nic *efx,
++ struct efx_special_buffer *buffer)
++{
++ efx_oword_t buf_tbl_upd;
++ unsigned int start = buffer->index;
++ unsigned int end = (buffer->index + buffer->entries - 1);
++
++ EFX_LOG(efx, "unmapping special buffers %d-%d\n",
++ buffer->index, buffer->index + buffer->entries - 1);
++
++ EFX_POPULATE_OWORD_4(buf_tbl_upd,
++ BUF_UPD_CMD, 0,
++ BUF_CLR_CMD, 1,
++ BUF_CLR_END_ID, end,
++ BUF_CLR_START_ID, start);
++ falcon_write(efx, &buf_tbl_upd, BUF_TBL_UPD_REG_KER);
++}
++
++/*
++ * Allocate a new Falcon special buffer
++ *
++ * This allocates memory for a new buffer, clears it and allocates a
++ * new buffer ID range. It does not write into Falcon's buffer table.
++ *
++ * This call will allocate 4kB buffers, since Falcon can't use 8kB
++ * buffers for event queues and descriptor rings. It will always
++ * allocate an even number of 4kB buffers, since when we're in
++ * half-entry mode for the buffer table we can only deal with pairs of
++ * buffers.
++ */
++static int falcon_alloc_special_buffer(struct efx_nic *efx,
++ struct efx_special_buffer *buffer,
++ unsigned int len)
++{
++ struct falcon_nic_data *nic_data = efx->nic_data;
++
++ /* Round size up to an 8kB boundary (i.e. pairs of 4kB buffers) */
++ len = (len + 8192 - 1) & ~(8192 - 1);
++
++ /* Allocate buffer as consistent PCI DMA space */
++ buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
++ &buffer->dma_addr);
++ if (!buffer->addr)
++ return -ENOMEM;
++ buffer->len = len;
++ buffer->entries = len / 4096;
++ BUG_ON(buffer->dma_addr & (FALCON_BUF_ALIGN - 1));
++
++ /* All zeros is a potentially valid event so memset to 0xff */
++ memset(buffer->addr, 0xff, len);
++
++ /* Select new buffer ID */
++ buffer->index = nic_data->resources.buffer_table_min;
++ nic_data->resources.buffer_table_min += buffer->entries;
++
++ EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
++ "(virt %p phys %lx)\n", buffer->index,
++ buffer->index + buffer->entries - 1,
++ (unsigned long long)buffer->dma_addr, len,
++ buffer->addr, virt_to_phys(buffer->addr));
++
++ return 0;
++}
++
++/*
++ * Initialise a Falcon special buffer
++ *
++ * This will define a buffer (previously allocated via
++ * falcon_alloc_special_buffer()) in Falcon's buffer table, allowing
++ * it to be used for event queues, descriptor rings etc.
++ */
++static int falcon_init_special_buffer(struct efx_nic *efx,
++ struct efx_special_buffer *buffer)
++{
++ EFX_BUG_ON_PARANOID(!buffer->addr);
++
++ /* Write buffer descriptors to NIC */
++ return falcon_pin_special_buffer_full(efx, buffer);
++}
++
++/* Unmaps a buffer from Falcon and clears the buffer table
++ * entries */
++static void falcon_fini_special_buffer(struct efx_nic *efx,
++ struct efx_special_buffer *buffer)
++{
++
++ if (!buffer->entries)
++ return;
++
++ falcon_clear_special_buffer_full(efx, buffer);
++}
++
++/* Release the buffer memory. */
++static void falcon_free_special_buffer(struct efx_nic *efx,
++ struct efx_special_buffer *buffer)
++{
++ if (!buffer->addr)
++ return;
++
++ EFX_LOG(efx, "deallocating special buffers %d-%d at %llx+%x "
++ "(virt %p phys %lx)\n", buffer->index,
++ buffer->index + buffer->entries - 1,
++ (unsigned long long)buffer->dma_addr, buffer->len,
++ buffer->addr, virt_to_phys(buffer->addr));
++
++ pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr,
++ buffer->dma_addr);
++ buffer->addr = NULL;
++ buffer->entries = 0;
++}
++
++/**************************************************************************
++ *
++ * Falcon generic buffer handling
++ * These buffers are used for interrupt status and MAC stats
++ *
++ **************************************************************************/
++
++static int falcon_alloc_buffer(struct efx_nic *efx,
++ struct efx_buffer *buffer, unsigned int len)
++{
++ buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
++ &buffer->dma_addr);
++ if (!buffer->addr)
++ return -ENOMEM;
++ buffer->len = len;
++ memset(buffer->addr, 0, len);
++ return 0;
++}
++
++static void falcon_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer)
++{
++ if (buffer->addr) {
++ pci_free_consistent(efx->pci_dev, buffer->len,
++ buffer->addr, buffer->dma_addr);
++ buffer->addr = NULL;
++ }
++}
++
++/**************************************************************************
++ *
++ * Falcon TX path
++ *
++ **************************************************************************/
++
++/* Returns a pointer to the specified transmit descriptor in the TX
++ * descriptor queue belonging to the specified channel.
++ */
++static inline efx_qword_t *falcon_tx_desc(struct efx_tx_queue *tx_queue,
++ unsigned int index)
++{
++ return (((efx_qword_t *) (tx_queue->txd.addr)) + index);
++}
++
++/* Update TX descriptor write pointer
++ * This writes to the TX_DESC_WPTR register for the specified
++ * channel's transmit descriptor ring.
++ */
++static inline void falcon_notify_tx_desc(struct efx_tx_queue *tx_queue)
++{
++ unsigned write_ptr;
++ efx_dword_t reg;
++
++ write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK;
++ EFX_POPULATE_DWORD_1(reg, TX_DESC_WPTR_DWORD, write_ptr);
++ falcon_writel_page(tx_queue->efx, &reg,
++ TX_DESC_UPD_REG_KER_DWORD, tx_queue->queue);
++}
++
++
++/* For each entry inserted into the software descriptor ring, create a
++ * descriptor in the hardware TX descriptor ring (in host memory), and
++ * write a doorbell.
++ */
++#if defined(EFX_USE_FASTCALL)
++void fastcall falcon_push_buffers(struct efx_tx_queue *tx_queue)
++#else
++void falcon_push_buffers(struct efx_tx_queue *tx_queue)
++#endif
++{
++
++ struct efx_tx_buffer *buffer;
++ efx_qword_t *txd;
++ unsigned write_ptr;
++
++ BUG_ON(tx_queue->write_count == tx_queue->insert_count);
++
++ do {
++ write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK;
++ buffer = &tx_queue->buffer[write_ptr];
++ txd = falcon_tx_desc(tx_queue, write_ptr);
++ ++tx_queue->write_count;
++
++ /* Create TX descriptor ring entry */
++ EFX_POPULATE_QWORD_5(*txd,
++ TX_KER_PORT, 0,
++ TX_KER_CONT, buffer->continuation,
++ TX_KER_BYTE_CNT, buffer->len,
++ TX_KER_BUF_REGION, 0,
++ TX_KER_BUF_ADR, buffer->dma_addr);
++ } while (tx_queue->write_count != tx_queue->insert_count);
++
++ wmb(); /* Ensure descriptors are written before they are fetched */
++ falcon_notify_tx_desc(tx_queue);
++}
++
++/* Allocate hardware resources for a TX queue */
++int falcon_probe_tx(struct efx_tx_queue *tx_queue)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ struct falcon_nic_data *nic_data = efx->nic_data;
++ int rc;
++
++ rc = falcon_alloc_special_buffer(efx, &tx_queue->txd,
++ FALCON_TXD_RING_SIZE *
++ sizeof(efx_qword_t));
++ if (rc)
++ return rc;
++
++ nic_data->resources.txq_min = max(nic_data->resources.txq_min,
++ (unsigned)tx_queue->queue + 1);
++
++ return 0;
++}
++
++/* Prepare channel's TX datapath. */
++int falcon_init_tx(struct efx_tx_queue *tx_queue)
++{
++ efx_oword_t tx_desc_ptr;
++ struct efx_nic *efx = tx_queue->efx;
++ int rc;
++
++ /* Pin TX descriptor ring */
++ rc = falcon_init_special_buffer(efx, &tx_queue->txd);
++ if (rc)
++ return rc;
++
++ /* Push TX descriptor ring to card */
++ EFX_POPULATE_OWORD_10(tx_desc_ptr,
++ TX_DESCQ_EN, 1,
++ TX_ISCSI_DDIG_EN, 0,
++ TX_ISCSI_HDIG_EN, 0,
++ TX_DESCQ_BUF_BASE_ID, tx_queue->txd.index,
++ TX_DESCQ_EVQ_ID, tx_queue->channel->evqnum,
++ TX_DESCQ_OWNER_ID, 0,
++ TX_DESCQ_LABEL, tx_queue->queue,
++ TX_DESCQ_SIZE, FALCON_TXD_RING_ORDER,
++ TX_DESCQ_TYPE, 0, /* kernel queue */
++ TX_NON_IP_DROP_DIS_B0, 1);
++
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ int csum = !(efx->net_dev->features & NETIF_F_IP_CSUM);
++ EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, csum);
++ EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, csum);
++ }
++
++ falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
++ tx_queue->queue);
++
++ if (FALCON_REV(efx) < FALCON_REV_B0) {
++ efx_oword_t reg;
++
++ /* Only 128 bits in this register */
++ BUG_ON(tx_queue->queue >= 128);
++
++ falcon_read(efx, &reg, TX_CHKSM_CFG_REG_KER_A1);
++ if (efx->net_dev->features & NETIF_F_IP_CSUM)
++ clear_bit_le(tx_queue->queue, (void *)&reg);
++ else
++ set_bit_le(tx_queue->queue, (void *)&reg);
++ falcon_write(efx, &reg, TX_CHKSM_CFG_REG_KER_A1);
++ }
++
++ return 0;
++}
++
++static int falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ struct efx_channel *channel = &efx->channel[0];
++ efx_oword_t tx_flush_descq;
++ unsigned int read_ptr, i;
++
++ /* Post a flush command */
++ EFX_POPULATE_OWORD_2(tx_flush_descq,
++ TX_FLUSH_DESCQ_CMD, 1,
++ TX_FLUSH_DESCQ, tx_queue->queue);
++ falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER);
++ msleep(FALCON_FLUSH_TIMEOUT);
++
++ /* If the NIC is resetting then don't bother checking */
++ if (EFX_WORKAROUND_7803(efx) || (efx->state == STATE_RESETTING))
++ return 0;
++
++ /* Look for a flush completed event */
++ read_ptr = channel->eventq_read_ptr;
++ for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
++ efx_qword_t *event = falcon_event(channel, read_ptr);
++ int ev_code, ev_sub_code, ev_queue;
++ if (!falcon_event_present(event))
++ break;
++
++ ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
++ ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
++ ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_TX_DESCQ_ID);
++ if ((ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) &&
++ (ev_queue == tx_queue->queue)) {
++ EFX_LOG(efx, "tx queue %d flush command succesful\n",
++ tx_queue->queue);
++ return 0;
++ }
++
++ read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
++ }
++
++ if (EFX_WORKAROUND_11557(efx)) {
++ efx_oword_t reg;
++ int enabled;
++
++ falcon_read_table(efx, &reg, efx->type->txd_ptr_tbl_base,
++ tx_queue->queue);
++ enabled = EFX_OWORD_FIELD(reg, TX_DESCQ_EN);
++ if (!enabled) {
++ EFX_LOG(efx, "tx queue %d disabled without a "
++ "flush event seen\n", tx_queue->queue);
++ return 0;
++ }
++ }
++
++ EFX_ERR(efx, "tx queue %d flush command timed out\n", tx_queue->queue);
++ return -ETIMEDOUT;
++}
++
++void falcon_fini_tx(struct efx_tx_queue *tx_queue)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ efx_oword_t tx_desc_ptr;
++
++ /* Stop the hardware using the queue */
++ if (falcon_flush_tx_queue(tx_queue))
++ EFX_ERR(efx, "failed to flush tx queue %d\n", tx_queue->queue);
++
++ /* Remove TX descriptor ring from card */
++ EFX_ZERO_OWORD(tx_desc_ptr);
++ falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
++ tx_queue->queue);
++
++ /* Unpin TX descriptor ring */
++ falcon_fini_special_buffer(efx, &tx_queue->txd);
++}
++
++/* Free buffers backing TX queue */
++void falcon_remove_tx(struct efx_tx_queue *tx_queue)
++{
++ falcon_free_special_buffer(tx_queue->efx, &tx_queue->txd);
++}
++
++/**************************************************************************
++ *
++ * Falcon RX path
++ *
++ **************************************************************************/
++
++/* Returns a pointer to the specified transmit descriptor in the RX
++ * descriptor queue.
++ */
++static inline efx_qword_t *falcon_rx_desc(struct efx_rx_queue *rx_queue,
++ unsigned int index)
++{
++ return (((efx_qword_t *) (rx_queue->rxd.addr)) + index);
++}
++
++/* This creates an entry in the RX descriptor queue corresponding to
++ * the receive buffer.
++ */
++static inline void falcon_build_rx_desc(struct efx_rx_queue *rx_queue,
++ unsigned index)
++{
++ struct efx_rx_buffer *rx_buf;
++ efx_qword_t *rxd;
++
++ rxd = falcon_rx_desc(rx_queue, index);
++ rx_buf = efx_rx_buffer(rx_queue, index);
++ EFX_POPULATE_QWORD_3(*rxd,
++ RX_KER_BUF_SIZE,
++ rx_buf->len -
++ rx_queue->efx->type->rx_buffer_padding,
++ RX_KER_BUF_REGION, 0,
++ RX_KER_BUF_ADR, rx_buf->dma_addr);
++}
++
++/* This writes to the RX_DESC_WPTR register for the specified receive
++ * descriptor ring.
++ */
++#if defined(EFX_USE_FASTCALL)
++void fastcall falcon_notify_rx_desc(struct efx_rx_queue *rx_queue)
++#else
++void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue)
++#endif
++{
++ efx_dword_t reg;
++ unsigned write_ptr;
++
++ while (rx_queue->notified_count != rx_queue->added_count) {
++ falcon_build_rx_desc(rx_queue,
++ rx_queue->notified_count &
++ FALCON_RXD_RING_MASK);
++ ++rx_queue->notified_count;
++ }
++
++ wmb();
++ write_ptr = rx_queue->added_count & FALCON_RXD_RING_MASK;
++ EFX_POPULATE_DWORD_1(reg, RX_DESC_WPTR_DWORD, write_ptr);
++ falcon_writel_page(rx_queue->efx, &reg,
++ RX_DESC_UPD_REG_KER_DWORD, rx_queue->queue);
++}
++
++int falcon_probe_rx(struct efx_rx_queue *rx_queue)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ struct falcon_nic_data *nic_data = efx->nic_data;
++ int rc;
++
++ rc = falcon_alloc_special_buffer(efx, &rx_queue->rxd,
++ FALCON_RXD_RING_SIZE *
++ sizeof(efx_qword_t));
++ if (rc)
++ return rc;
++
++ /* Increment the rxq_min counter */
++ nic_data->resources.rxq_min = max(nic_data->resources.rxq_min,
++ (unsigned)rx_queue->queue + 1);
++
++ return 0;
++}
++
++int falcon_init_rx(struct efx_rx_queue *rx_queue)
++{
++ efx_oword_t rx_desc_ptr;
++ struct efx_nic *efx = rx_queue->efx;
++ int rc;
++ int is_b0 = FALCON_REV(efx) >= FALCON_REV_B0;
++ int iscsi_digest_en = is_b0;
++
++ EFX_LOG(efx, "RX queue %d ring in special buffers %d-%d\n",
++ rx_queue->queue, rx_queue->rxd.index,
++ rx_queue->rxd.index + rx_queue->rxd.entries - 1);
++
++ /* Pin RX descriptor ring */
++ rc = falcon_init_special_buffer(efx, &rx_queue->rxd);
++ if (rc)
++ return rc;
++
++ /* Push RX descriptor ring to card */
++ EFX_POPULATE_OWORD_10(rx_desc_ptr,
++ RX_ISCSI_DDIG_EN, iscsi_digest_en,
++ RX_ISCSI_HDIG_EN, iscsi_digest_en,
++ RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
++ RX_DESCQ_EVQ_ID, rx_queue->channel->evqnum,
++ RX_DESCQ_OWNER_ID, 0,
++ RX_DESCQ_LABEL, rx_queue->queue,
++ RX_DESCQ_SIZE, FALCON_RXD_RING_ORDER,
++ RX_DESCQ_TYPE, 0 /* kernel queue */ ,
++ /* For >=B0 this is scatter so disable */
++ RX_DESCQ_JUMBO, !is_b0,
++ RX_DESCQ_EN, 1);
++ falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
++ rx_queue->queue);
++ return 0;
++}
++
++static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ struct efx_channel *channel = &efx->channel[0];
++ unsigned int read_ptr, i;
++ efx_oword_t rx_flush_descq;
++
++ /* Post a flush command */
++ EFX_POPULATE_OWORD_2(rx_flush_descq,
++ RX_FLUSH_DESCQ_CMD, 1,
++ RX_FLUSH_DESCQ, rx_queue->queue);
++
++ falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER);
++ msleep(FALCON_FLUSH_TIMEOUT);
++
++ /* If the NIC is resetting then don't bother checking */
++ if (EFX_WORKAROUND_7803(efx) || (efx->state == STATE_RESETTING))
++ return 0;
++
++ /* Look for a flush completed event */
++ read_ptr = channel->eventq_read_ptr;
++ for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
++ efx_qword_t *event = falcon_event(channel, read_ptr);
++ int ev_code, ev_sub_code, ev_queue, ev_failed;
++ if (!falcon_event_present(event))
++ break;
++
++ ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
++ ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
++ ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_DESCQ_ID);
++ ev_failed = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_FLUSH_FAIL);
++
++ if ((ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) &&
++ (ev_queue == rx_queue->queue)) {
++ if (ev_failed) {
++ EFX_INFO(efx, "rx queue %d flush command "
++ "failed\n", rx_queue->queue);
++ return -EAGAIN;
++ } else {
++ EFX_LOG(efx, "rx queue %d flush command "
++ "succesful\n", rx_queue->queue);
++ return 0;
++ }
++ }
++
++ read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
++ }
++
++ if (EFX_WORKAROUND_11557(efx)) {
++ efx_oword_t reg;
++ int enabled;
++
++ falcon_read_table(efx, &reg, efx->type->rxd_ptr_tbl_base,
++ rx_queue->queue);
++ enabled = EFX_OWORD_FIELD(reg, RX_DESCQ_EN);
++ if (!enabled) {
++ EFX_LOG(efx, "rx queue %d disabled without a "
++ "flush event seen\n", rx_queue->queue);
++ return 0;
++ }
++ }
++
++ EFX_ERR(efx, "rx queue %d flush command timed out\n", rx_queue->queue);
++ return -ETIMEDOUT;
++}
++
++void falcon_fini_rx(struct efx_rx_queue *rx_queue)
++{
++ efx_oword_t rx_desc_ptr;
++ struct efx_nic *efx = rx_queue->efx;
++ int i, rc;
++
++ /* Try and flush the rx queue. This may need to be repeated */
++ for (i = 0; i < 5; i++) {
++ rc = falcon_flush_rx_queue(rx_queue);
++ if (rc == -EAGAIN)
++ continue;
++ break;
++ }
++ if (rc)
++ EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue);
++
++ /* Remove RX descriptor ring from card */
++ EFX_ZERO_OWORD(rx_desc_ptr);
++ falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
++ rx_queue->queue);
++
++ /* Unpin RX descriptor ring */
++ falcon_fini_special_buffer(efx, &rx_queue->rxd);
++}
++
++/* Free buffers backing RX queue */
++void falcon_remove_rx(struct efx_rx_queue *rx_queue)
++{
++ falcon_free_special_buffer(rx_queue->efx, &rx_queue->rxd);
++}
++
++/**************************************************************************
++ *
++ * Falcon event queue processing
++ * Event queues are processed by per-channel tasklets.
++ *
++ **************************************************************************/
++
++/* Update a channel's event queue's read pointer (RPTR) register
++ *
++ * This writes the EVQ_RPTR_REG register for the specified channel's
++ * event queue.
++ *
++ * Note that EVQ_RPTR_REG contains the index of the "last read" event,
++ * whereas channel->eventq_read_ptr contains the index of the "next to
++ * read" event.
++ */
++#if defined(EFX_USE_FASTCALL)
++void fastcall falcon_eventq_read_ack(struct efx_channel *channel)
++#else
++void falcon_eventq_read_ack(struct efx_channel *channel)
++#endif
++{
++ efx_dword_t reg;
++ struct efx_nic *efx = channel->efx;
++
++ EFX_POPULATE_DWORD_1(reg, EVQ_RPTR_DWORD, channel->eventq_read_ptr);
++ falcon_writel_table(efx, &reg, efx->type->evq_rptr_tbl_base,
++ channel->evqnum);
++}
++
++/* Use HW to insert a SW defined event */
++void falcon_generate_event(struct efx_channel *channel, efx_qword_t *event)
++{
++ efx_oword_t drv_ev_reg;
++
++ EFX_POPULATE_OWORD_2(drv_ev_reg,
++ DRV_EV_QID, channel->evqnum,
++ DRV_EV_DATA,
++ EFX_QWORD_FIELD64(*event, WHOLE_EVENT));
++ falcon_write(channel->efx, &drv_ev_reg, DRV_EV_REG_KER);
++}
++
++/* Handle a transmit completion event
++ *
++ * Falcon batches TX completion events; the message we receive is of
++ * the form "complete all TX events up to this index".
++ */
++static inline void falcon_handle_tx_event(struct efx_channel *channel,
++ efx_qword_t *event)
++{
++ unsigned int tx_ev_desc_ptr;
++ unsigned int tx_ev_q_label;
++ struct efx_tx_queue *tx_queue;
++ struct efx_nic *efx = channel->efx;
++
++ if (likely(EFX_QWORD_FIELD(*event, TX_EV_COMP))) {
++ /* Transmit completion */
++ tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, TX_EV_DESC_PTR);
++ tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL);
++ tx_queue = &efx->tx_queue[tx_ev_q_label];
++ efx_xmit_done(tx_queue, tx_ev_desc_ptr);
++ } else if (EFX_QWORD_FIELD(*event, TX_EV_WQ_FF_FULL)) {
++ /* Rewrite the FIFO write pointer */
++ tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL);
++ tx_queue = &efx->tx_queue[tx_ev_q_label];
++
++ if (efx->net_dev_registered)
++ netif_tx_lock(efx->net_dev);
++ falcon_notify_tx_desc(tx_queue);
++ if (efx->net_dev_registered)
++ netif_tx_unlock(efx->net_dev);
++ } else if (EFX_QWORD_FIELD(*event, TX_EV_PKT_ERR) &&
++ EFX_WORKAROUND_10727(efx)) {
++ efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
++ } else {
++ EFX_ERR(efx, "channel %d unexpected TX event "
++ EFX_QWORD_FMT"\n", channel->channel,
++ EFX_QWORD_VAL(*event));
++ }
++}
++
++/* Check received packet's destination MAC address. */
++static int check_dest_mac(struct efx_rx_queue *rx_queue,
++ const efx_qword_t *event)
++{
++ struct efx_rx_buffer *rx_buf;
++ struct efx_nic *efx = rx_queue->efx;
++ int rx_ev_desc_ptr;
++ struct ethhdr *eh;
++
++ if (efx->promiscuous)
++ return 1;
++
++ rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, RX_EV_DESC_PTR);
++ rx_buf = efx_rx_buffer(rx_queue, rx_ev_desc_ptr);
++ eh = (struct ethhdr *)rx_buf->data;
++ if (memcmp(eh->h_dest, efx->net_dev->dev_addr, ETH_ALEN))
++ return 0;
++ return 1;
++}
++
++/* Detect errors included in the rx_evt_pkt_ok bit. */
++static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
++ const efx_qword_t *event,
++ unsigned *rx_ev_pkt_ok,
++ int *discard, int byte_count)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
++ unsigned rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
++ unsigned rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
++ unsigned rx_ev_pkt_type, rx_ev_other_err, rx_ev_pause_frm;
++ unsigned rx_ev_ip_frag_err, rx_ev_hdr_type, rx_ev_mcast_pkt;
++ int snap, non_ip;
++
++ rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE);
++ rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT);
++ rx_ev_tobe_disc = EFX_QWORD_FIELD(*event, RX_EV_TOBE_DISC);
++ rx_ev_pkt_type = EFX_QWORD_FIELD(*event, RX_EV_PKT_TYPE);
++ rx_ev_buf_owner_id_err = EFX_QWORD_FIELD(*event,
++ RX_EV_BUF_OWNER_ID_ERR);
++ rx_ev_ip_frag_err = EFX_QWORD_FIELD(*event, RX_EV_IF_FRAG_ERR);
++ rx_ev_ip_hdr_chksum_err = EFX_QWORD_FIELD(*event,
++ RX_EV_IP_HDR_CHKSUM_ERR);
++ rx_ev_tcp_udp_chksum_err = EFX_QWORD_FIELD(*event,
++ RX_EV_TCP_UDP_CHKSUM_ERR);
++ rx_ev_eth_crc_err = EFX_QWORD_FIELD(*event, RX_EV_ETH_CRC_ERR);
++ rx_ev_frm_trunc = EFX_QWORD_FIELD(*event, RX_EV_FRM_TRUNC);
++ rx_ev_drib_nib = ((FALCON_REV(efx) >= FALCON_REV_B0) ?
++ 0 : EFX_QWORD_FIELD(*event, RX_EV_DRIB_NIB));
++ rx_ev_pause_frm = EFX_QWORD_FIELD(*event, RX_EV_PAUSE_FRM_ERR);
++
++ /* Every error apart from tobe_disc and pause_frm */
++ rx_ev_other_err = (rx_ev_drib_nib | rx_ev_tcp_udp_chksum_err |
++ rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
++ rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
++
++ snap = (rx_ev_pkt_type == RX_EV_PKT_TYPE_LLC_DECODE) ||
++ (rx_ev_pkt_type == RX_EV_PKT_TYPE_VLAN_LLC_DECODE);
++ non_ip = (rx_ev_hdr_type == RX_EV_HDR_TYPE_NON_IP_DECODE);
++
++ /* SFC bug 5475/8970: The Falcon XMAC incorrectly calculates the
++ * length field of an LLC frame, which sets TOBE_DISC. We could set
++ * PASS_LEN_ERR, but we want the MAC to filter out short frames (to
++ * protect the RX block).
++ *
++ * bug5475 - LLC/SNAP: Falcon identifies SNAP packets.
++ * bug8970 - LLC/noSNAP: Falcon does not provide an LLC flag.
++ * LLC can't encapsulate IP, so by definition
++ * these packets are NON_IP.
++ *
++ * Unicast mismatch will also cause TOBE_DISC, so the driver needs
++ * to check this.
++ */
++ if (EFX_WORKAROUND_5475(efx) && rx_ev_tobe_disc && (snap || non_ip)) {
++ /* If all the other flags are zero then we can state the
++ * entire packet is ok, which will flag to the kernel not
++ * to recalculate checksums.
++ */
++ if (!(non_ip | rx_ev_other_err | rx_ev_pause_frm))
++ *rx_ev_pkt_ok = 1;
++
++ rx_ev_tobe_disc = 0;
++
++ /* TOBE_DISC is set for unicast mismatch. But given that
++ * we can't trust TOBE_DISC here, we must validate the dest
++ * MAC address ourselves.
++ */
++ if (!rx_ev_mcast_pkt && !check_dest_mac(rx_queue, event))
++ rx_ev_tobe_disc = 1;
++ }
++
++ /* Count errors that are not in MAC stats. */
++ if (rx_ev_frm_trunc)
++ ++rx_queue->channel->n_rx_frm_trunc;
++ else if (rx_ev_tobe_disc)
++ ++rx_queue->channel->n_rx_tobe_disc;
++ else if (rx_ev_ip_hdr_chksum_err)
++ ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
++ else if (rx_ev_tcp_udp_chksum_err)
++ ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
++ if (rx_ev_ip_frag_err)
++ ++rx_queue->channel->n_rx_ip_frag_err;
++
++ /* The frame must be discarded if any of these are true. */
++ *discard = (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib |
++ rx_ev_tobe_disc | rx_ev_pause_frm);
++
++ /* TOBE_DISC is expected on unicast mismatches; don't print out an
++ * error message. FRM_TRUNC indicates RXDP dropped the packet due
++ * to a FIFO overflow.
++ */
++#ifdef EFX_ENABLE_DEBUG
++ if (rx_ev_other_err) {
++ EFX_INFO_RL(efx, " RX queue %d unexpected RX event "
++ EFX_QWORD_FMT "%s%s%s%s%s%s%s%s%s\n",
++ rx_queue->queue, EFX_QWORD_VAL(*event),
++ rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
++ rx_ev_ip_hdr_chksum_err ?
++ " [IP_HDR_CHKSUM_ERR]" : "",
++ rx_ev_tcp_udp_chksum_err ?
++ " [TCP_UDP_CHKSUM_ERR]" : "",
++ rx_ev_eth_crc_err ? " [ETH_CRC_ERR]" : "",
++ rx_ev_frm_trunc ? " [FRM_TRUNC]" : "",
++ rx_ev_drib_nib ? " [DRIB_NIB]" : "",
++ rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
++ rx_ev_pause_frm ? " [PAUSE]" : "",
++ snap ? " [SNAP/LLC]" : "");
++ }
++#endif
++
++ if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) &&
++ efx->phy_type == PHY_TYPE_10XPRESS))
++ tenxpress_crc_err(efx);
++}
++
++
++/* Handle receive events that are not in-order. */
++static void falcon_handle_rx_bad_index(struct efx_rx_queue *rx_queue,
++ unsigned index)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned expected, dropped;
++
++ expected = rx_queue->removed_count & FALCON_RXD_RING_MASK;
++ dropped = ((index + FALCON_RXD_RING_SIZE - expected) &
++ FALCON_RXD_RING_MASK);
++ EFX_INFO(efx, "dropped %d events (index=%d expected=%d)\n",
++ dropped, index, expected);
++
++ atomic_inc(&efx->errors.missing_event);
++ efx_schedule_reset(efx, EFX_WORKAROUND_5676(efx) ?
++ RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
++}
++
++
++/* Handle a packet received event
++ *
++ * Falcon silicon gives a "discard" flag if it's a unicast packet with the
++ * wrong destination address
++ * Also "is multicast" and "matches multicast filter" flags can be used to
++ * discard non-matching multicast packets.
++ */
++static inline int falcon_handle_rx_event(struct efx_channel *channel,
++ const efx_qword_t *event)
++{
++ unsigned int rx_ev_q_label, rx_ev_desc_ptr, rx_ev_byte_cnt;
++ unsigned int rx_ev_pkt_ok, rx_ev_hdr_type, rx_ev_mcast_pkt;
++ unsigned expected_ptr;
++ int discard = 0, checksummed;
++ struct efx_rx_queue *rx_queue;
++ struct efx_nic *efx = channel->efx;
++
++ /* Basic packet information */
++ rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, RX_EV_BYTE_CNT);
++ rx_ev_pkt_ok = EFX_QWORD_FIELD(*event, RX_EV_PKT_OK);
++ rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE);
++ WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_JUMBO_CONT));
++ WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_SOP) != 1);
++
++ rx_ev_q_label = EFX_QWORD_FIELD(*event, RX_EV_Q_LABEL);
++ rx_queue = &efx->rx_queue[rx_ev_q_label];
++
++ rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, RX_EV_DESC_PTR);
++ expected_ptr = rx_queue->removed_count & FALCON_RXD_RING_MASK;
++ if (unlikely(rx_ev_desc_ptr != expected_ptr)) {
++ falcon_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
++ return rx_ev_q_label;
++ }
++
++ if (likely(rx_ev_pkt_ok)) {
++ /* If packet is marked as OK and packet type is TCP/IPv4 or
++ * UDP/IPv4, then we can rely on the hardware checksum.
++ */
++ checksummed = RX_EV_HDR_TYPE_HAS_CHECKSUMS(rx_ev_hdr_type);
++ } else {
++ falcon_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok,
++ &discard, rx_ev_byte_cnt);
++ checksummed = 0;
++ }
++
++ /* Detect multicast packets that didn't match the filter */
++ rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT);
++ if (rx_ev_mcast_pkt) {
++ unsigned int rx_ev_mcast_hash_match =
++ EFX_QWORD_FIELD(*event, RX_EV_MCAST_HASH_MATCH);
++
++ if (unlikely(!rx_ev_mcast_hash_match))
++ discard = 1;
++ }
++
++ /* Handle received packet */
++ efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt,
++ checksummed, discard);
++
++ return rx_ev_q_label;
++}
++
++/* Global events are basically PHY events */
++static void falcon_handle_global_event(struct efx_channel *channel,
++ efx_qword_t *event)
++{
++ struct efx_nic *efx = channel->efx;
++ int is_phy_event = 0, handled = 0;
++
++ /* Check for interrupt on either port. Some boards have a
++ * single PHY wired to the interrupt line for port 1. */
++ if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
++ EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
++ EFX_QWORD_FIELD(*event, XG_PHY_INTR))
++ is_phy_event = 1;
++
++ if ((FALCON_REV(efx) >= FALCON_REV_B0) &&
++ EFX_OWORD_FIELD(*event, XG_MNT_INTR_B0))
++ is_phy_event = 1;
++
++ if (is_phy_event) {
++ efx->phy_op->clear_interrupt(efx);
++ queue_work(efx->workqueue, &efx->reconfigure_work);
++ handled = 1;
++ }
++
++ if (EFX_QWORD_FIELD_VER(efx, *event, RX_RECOVERY)) {
++ EFX_ERR(efx, "channel %d seen global RX_RESET "
++ "event. Resetting.\n", channel->channel);
++
++ atomic_inc(&efx->errors.rx_reset);
++ efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
++ RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
++ handled = 1;
++ }
++
++ if (!handled)
++ EFX_ERR(efx, "channel %d unknown global event "
++ EFX_QWORD_FMT "\n", channel->channel,
++ EFX_QWORD_VAL(*event));
++}
++
++static void falcon_handle_driver_event(struct efx_channel *channel,
++ efx_qword_t *event)
++{
++ struct efx_nic *efx = channel->efx;
++ unsigned int ev_sub_code;
++ unsigned int ev_sub_data;
++
++ ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
++ ev_sub_data = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_DATA);
++
++ switch (ev_sub_code) {
++ case TX_DESCQ_FLS_DONE_EV_DECODE:
++ EFX_TRACE(efx, "channel %d TXQ %d flushed\n",
++ channel->channel, ev_sub_data);
++ EFX_DL_CALLBACK(efx, event, event);
++ break;
++ case RX_DESCQ_FLS_DONE_EV_DECODE:
++ EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
++ channel->channel, ev_sub_data);
++ EFX_DL_CALLBACK(efx, event, event);
++ break;
++ case EVQ_INIT_DONE_EV_DECODE:
++ EFX_LOG(efx, "channel %d EVQ %d initialised\n",
++ channel->channel, ev_sub_data);
++ break;
++ case SRM_UPD_DONE_EV_DECODE:
++ EFX_TRACE(efx, "channel %d SRAM update done\n",
++ channel->channel);
++ EFX_DL_CALLBACK(efx, event, event);
++ break;
++ case WAKE_UP_EV_DECODE:
++ EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
++ channel->channel, ev_sub_data);
++ EFX_DL_CALLBACK(efx, event, event);
++ break;
++ case TIMER_EV_DECODE:
++ EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
++ channel->channel, ev_sub_data);
++ EFX_DL_CALLBACK(efx, event, event);
++ break;
++ case RX_RECOVERY_EV_DECODE:
++ EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
++ "Resetting.\n", channel->channel);
++
++ atomic_inc(&efx->errors.rx_reset);
++ efx_schedule_reset(efx,
++ EFX_WORKAROUND_6555(efx) ?
++ RESET_TYPE_RX_RECOVERY :
++ RESET_TYPE_DISABLE);
++ break;
++ case RX_DSC_ERROR_EV_DECODE:
++ EFX_ERR(efx, "RX DMA Q %d reports descriptor fetch error."
++ " RX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
++ atomic_inc(&efx->errors.rx_desc_fetch);
++ efx_schedule_reset(efx, RESET_TYPE_RX_DESC_FETCH);
++ break;
++ case TX_DSC_ERROR_EV_DECODE:
++ EFX_ERR(efx, "TX DMA Q %d reports descriptor fetch error."
++ " TX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
++ atomic_inc(&efx->errors.tx_desc_fetch);
++ efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
++ break;
++ default:
++ EFX_TRACE(efx, "channel %d unknown driver event code %d "
++ "data %04x\n", channel->channel, ev_sub_code,
++ ev_sub_data);
++ EFX_DL_CALLBACK(efx, event, event);
++ break;
++ }
++}
++
++#if defined(EFX_USE_FASTCALL)
++int fastcall falcon_process_eventq(struct efx_channel *channel, int *rx_quota)
++#else
++int falcon_process_eventq(struct efx_channel *channel, int *rx_quota)
++#endif
++{
++ unsigned int read_ptr;
++ efx_qword_t event, *p_event;
++ int ev_code;
++ int rxq;
++ int rxdmaqs = 0;
++
++ read_ptr = channel->eventq_read_ptr;
++
++ do {
++ p_event = falcon_event(channel, read_ptr);
++ event = *p_event;
++
++ if (!falcon_event_present(&event))
++ /* End of events */
++ break;
++
++ EFX_TRACE(channel->efx, "channel %d event is "EFX_QWORD_FMT"\n",
++ channel->channel, EFX_QWORD_VAL(event));
++
++ /* Clear this event by marking it all ones */
++ EFX_SET_QWORD(*p_event);
++
++ ev_code = EFX_QWORD_FIELD(event, EV_CODE);
++
++ switch (ev_code) {
++ case RX_IP_EV_DECODE:
++ rxq = falcon_handle_rx_event(channel, &event);
++ rxdmaqs |= (1 << rxq);
++ (*rx_quota)--;
++ break;
++ case TX_IP_EV_DECODE:
++ falcon_handle_tx_event(channel, &event);
++ break;
++ case DRV_GEN_EV_DECODE:
++ channel->eventq_magic
++ = EFX_QWORD_FIELD(event, EVQ_MAGIC);
++ EFX_LOG(channel->efx, "channel %d received generated "
++ "event "EFX_QWORD_FMT"\n", channel->channel,
++ EFX_QWORD_VAL(event));
++ break;
++ case GLOBAL_EV_DECODE:
++ falcon_handle_global_event(channel, &event);
++ break;
++ case DRIVER_EV_DECODE:
++ falcon_handle_driver_event(channel, &event);
++ break;
++ default:
++ EFX_ERR(channel->efx, "channel %d unknown event type %d"
++ " (data " EFX_QWORD_FMT ")\n", channel->channel,
++ ev_code, EFX_QWORD_VAL(event));
++ }
++
++ /* Increment read pointer */
++ read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
++
++ } while (*rx_quota);
++
++ channel->eventq_read_ptr = read_ptr;
++ return rxdmaqs;
++}
++
++void falcon_set_int_moderation(struct efx_channel *channel)
++{
++ efx_dword_t timer_cmd;
++ struct efx_nic *efx = channel->efx;
++
++ /* Set timer register */
++ if (channel->irq_moderation) {
++ /* Round to resolution supported by hardware. The value we
++ * program is based at 0. So actual interrupt moderation
++ * achieved is ((x + 1) * res).
++ */
++ unsigned int res = 5;
++ channel->irq_moderation -= (channel->irq_moderation % res);
++ if (channel->irq_moderation < res)
++ channel->irq_moderation = res;
++ EFX_POPULATE_DWORD_2(timer_cmd,
++ TIMER_MODE, TIMER_MODE_INT_HLDOFF,
++ TIMER_VAL,
++ (channel->irq_moderation / res) - 1);
++ } else {
++ EFX_POPULATE_DWORD_2(timer_cmd,
++ TIMER_MODE, TIMER_MODE_DIS,
++ TIMER_VAL, 0);
++ }
++ falcon_writel_page_locked(efx, &timer_cmd, TIMER_CMD_REG_KER,
++ channel->evqnum);
++
++}
++
++/* Allocate buffer table entries for event queue */
++int falcon_probe_eventq(struct efx_channel *channel)
++{
++ struct efx_nic *efx = channel->efx;
++ struct falcon_nic_data *nic_data = efx->nic_data;
++ unsigned int evq_size;
++ int rc;
++
++ evq_size = FALCON_EVQ_SIZE * sizeof(efx_qword_t);
++ rc = falcon_alloc_special_buffer(efx, &channel->eventq, evq_size);
++ if (rc)
++ return rc;
++
++ nic_data->resources.evq_int_min = max(nic_data->resources.evq_int_min,
++ (unsigned)channel->evqnum + 1);
++
++ return 0;
++}
++
++int falcon_init_eventq(struct efx_channel *channel)
++{
++ efx_oword_t evq_ptr;
++ struct efx_nic *efx = channel->efx;
++ int rc;
++
++ EFX_LOG(efx, "channel %d event queue in special buffers %d-%d\n",
++ channel->channel, channel->eventq.index,
++ channel->eventq.index + channel->eventq.entries - 1);
++
++ /* Pin event queue buffer */
++ rc = falcon_init_special_buffer(efx, &channel->eventq);
++ if (rc)
++ return rc;
++
++ /* Fill event queue with all ones (i.e. empty events) */
++ memset(channel->eventq.addr, 0xff, channel->eventq.len);
++
++ /* Push event queue to card */
++ EFX_POPULATE_OWORD_3(evq_ptr,
++ EVQ_EN, 1,
++ EVQ_SIZE, FALCON_EVQ_ORDER,
++ EVQ_BUF_BASE_ID, channel->eventq.index);
++ falcon_write_table(efx, &evq_ptr, efx->type->evq_ptr_tbl_base,
++ channel->evqnum);
++
++ falcon_set_int_moderation(channel);
++
++ return 0;
++}
++
++void falcon_fini_eventq(struct efx_channel *channel)
++{
++ efx_oword_t eventq_ptr;
++ struct efx_nic *efx = channel->efx;
++
++ /* Remove event queue from card */
++ EFX_ZERO_OWORD(eventq_ptr);
++ falcon_write_table(efx, &eventq_ptr, efx->type->evq_ptr_tbl_base,
++ channel->evqnum);
++
++ /* Unpin event queue */
++ falcon_fini_special_buffer(efx, &channel->eventq);
++}
++
++/* Free buffers backing event queue */
++void falcon_remove_eventq(struct efx_channel *channel)
++{
++ falcon_free_special_buffer(channel->efx, &channel->eventq);
++}
++
++
++/* Generates a test event on the event queue. A subsequent call to
++ * process_eventq() should pick up the event and place the value of
++ * "magic" into channel->eventq_magic;
++ */
++void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic)
++{
++ efx_qword_t test_event;
++
++ EFX_POPULATE_QWORD_2(test_event,
++ EV_CODE, DRV_GEN_EV_DECODE,
++ EVQ_MAGIC, magic);
++ falcon_generate_event(channel, &test_event);
++}
++
++
++/**************************************************************************
++ *
++ * Falcon hardware interrupts
++ * The hardware interrupt handler does very little work; all the event
++ * queue processing is carried out by per-channel tasklets.
++ *
++ **************************************************************************/
++
++/* Enable/disable/generate Falcon interrupts */
++static inline void falcon_interrupts(struct efx_nic *efx, int enabled,
++ int force)
++{
++ efx_oword_t int_en_reg_ker;
++
++ EFX_POPULATE_OWORD_2(int_en_reg_ker,
++ KER_INT_KER, force,
++ DRV_INT_EN_KER, enabled);
++ falcon_write(efx, &int_en_reg_ker, INT_EN_REG_KER);
++}
++
++void falcon_enable_interrupts(struct efx_nic *efx)
++{
++ efx_oword_t int_adr_reg_ker;
++ struct efx_channel *channel;
++
++ /* Zero INT_KER */
++ EFX_ZERO_OWORD(*((efx_oword_t *) efx->irq_status.addr));
++ wmb(); /* Ensure interrupt vector is clear before interrupts enabled */
++
++ /* Program INT_ADR_KER_REG */
++ EFX_POPULATE_OWORD_2(int_adr_reg_ker,
++ NORM_INT_VEC_DIS_KER, EFX_INT_MODE_USE_MSI(efx),
++ INT_ADR_KER, efx->irq_status.dma_addr);
++ falcon_write(efx, &int_adr_reg_ker, INT_ADR_REG_KER);
++
++ /* Enable interrupts */
++ falcon_interrupts(efx, 1, 0);
++
++ /* Force processing of all the channels to get the EVQ RPTRs up to
++ date */
++ efx_for_each_channel_with_interrupt(channel, efx)
++ efx_schedule_channel(channel);
++}
++
++void falcon_disable_interrupts(struct efx_nic *efx)
++{
++ /* Disable interrupts */
++ falcon_interrupts(efx, 0, 0);
++}
++
++/* Generate a Falcon test interrupt
++ * Interrupt must already have been enabled, otherwise nasty things
++ * may happen.
++ */
++void falcon_generate_interrupt(struct efx_nic *efx)
++{
++ falcon_interrupts(efx, 1, 1);
++}
++
++/* Acknowledge a legacy interrupt from Falcon
++ *
++ * This acknowledges a legacy (not MSI) interrupt via INT_ACK_KER_REG.
++ *
++ * Due to SFC bug 3706 (silicon revision <=A1) reads can be duplicated in the
++ * BIU. Interrupt acknowledge is read sensitive so must write instead
++ * (then read to ensure the BIU collector is flushed)
++ *
++ * NB most hardware supports MSI interrupts
++ */
++static inline void falcon_irq_ack_a1(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++
++ EFX_POPULATE_DWORD_1(reg, INT_ACK_DUMMY_DATA, 0xb7eb7e);
++ falcon_writel(efx, &reg, INT_ACK_REG_KER_A1);
++ falcon_readl(efx, &reg, WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1);
++}
++
++/* Process a fatal interrupt
++ * Disable bus mastering ASAP and schedule a reset
++ */
++static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx)
++{
++ efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
++ efx_oword_t fatal_intr;
++ int error, mem_perr;
++ static int n_int_errors;
++
++ falcon_read(efx, &fatal_intr, FATAL_INTR_REG_KER);
++ error = EFX_OWORD_FIELD(fatal_intr, INT_KER_ERROR);
++
++ EFX_ERR(efx, "SYSTEM ERROR " EFX_OWORD_FMT " status "
++ EFX_OWORD_FMT ": %s\n", EFX_OWORD_VAL(*int_ker),
++ EFX_OWORD_VAL(fatal_intr),
++ error ? "disabling bus mastering" : "no recognised error");
++ if (error == 0)
++ goto out;
++
++ /* If this is a memory parity error dump which blocks are offending */
++ mem_perr = EFX_OWORD_FIELD(fatal_intr, MEM_PERR_INT_KER);
++ if (mem_perr) {
++ efx_oword_t reg;
++ falcon_read(efx, &reg, MEM_STAT_REG_KER);
++ EFX_ERR(efx, "SYSTEM ERROR: memory parity error "
++ EFX_OWORD_FMT "\n", EFX_OWORD_VAL(reg));
++ }
++
++ /* Disable DMA bus mastering on both devices */
++ pci_disable_device(efx->pci_dev);
++ if (efx->type->is_dual_func)
++ pci_disable_device(efx->pci_dev2);
++
++ if (++n_int_errors < FALCON_MAX_INT_ERRORS) {
++ EFX_ERR(efx, "SYSTEM ERROR - reset scheduled\n");
++ efx_schedule_reset(efx, RESET_TYPE_INT_ERROR);
++ } else {
++ EFX_ERR(efx, "SYSTEM ERROR - max number of errors seen."
++ "NIC will be disabled\n");
++ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
++ }
++out:
++ return IRQ_HANDLED;
++}
++
++/* Handle a legacy interrupt from Falcon
++ * Acknowledges the interrupt and schedule event queue processing.
++ *
++ * This routine must guarantee not to touch the hardware when
++ * interrupts are disabled, to allow for correct semantics of
++ * efx_suspend() and efx_resume().
++ */
++#if !defined(EFX_HAVE_IRQ_HANDLER_REGS)
++static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id)
++#else
++static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id,
++ struct pt_regs *regs
++ __attribute__ ((unused)))
++#endif
++{
++ struct efx_nic *efx = (struct efx_nic *)dev_id;
++ efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
++ struct efx_channel *channel;
++ efx_dword_t reg;
++ u32 queues;
++ int syserr;
++
++ /* Read the ISR which also ACKs the interrupts */
++ falcon_readl(efx, &reg, INT_ISR0_B0);
++ queues = EFX_EXTRACT_DWORD(reg, 0, 31);
++
++ /* Check to see if we have a serious error condition */
++ syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT);
++ if (unlikely(syserr))
++ return falcon_fatal_interrupt(efx);
++
++ if (queues == 0)
++ return IRQ_NONE;
++
++ efx->last_irq_cpu = raw_smp_processor_id();
++ EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n",
++ irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg));
++
++ /* Schedule processing of any interrupting queues */
++ channel = &efx->channel[0];
++ while (queues) {
++ if (queues & 0x01)
++ efx_schedule_channel(channel);
++ channel++;
++ queues >>= 1;
++ }
++
++ return IRQ_HANDLED;
++}
++
++
++#if !defined(EFX_HAVE_IRQ_HANDLER_REGS)
++static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
++#else
++static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id,
++ struct pt_regs *regs
++ __attribute__ ((unused)))
++#endif
++{
++ struct efx_nic *efx = (struct efx_nic *)dev_id;
++ efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
++ struct efx_channel *channel;
++ int syserr;
++ int queues;
++
++ /* Check to see if this is our interrupt. If it isn't, we
++ * exit without having touched the hardware.
++ */
++ if (unlikely(EFX_OWORD_IS_ZERO(*int_ker))) {
++ EFX_TRACE(efx, "IRQ %d on CPU %d not for me\n", irq,
++ raw_smp_processor_id());
++ return IRQ_NONE;
++ }
++ efx->last_irq_cpu = raw_smp_processor_id();
++ EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
++ irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
++
++ /* Check to see if we have a serious error condition */
++ syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT);
++ if (unlikely(syserr))
++ return falcon_fatal_interrupt(efx);
++
++ /* Determine interrupting queues, clear interrupt status
++ * register and acknowledge the device interrupt.
++ */
++ BUILD_BUG_ON(INT_EVQS_WIDTH > EFX_MAX_CHANNELS);
++ queues = EFX_OWORD_FIELD(*int_ker, INT_EVQS);
++ EFX_ZERO_OWORD(*int_ker);
++ wmb(); /* Ensure the vector is cleared before interrupt ack */
++ falcon_irq_ack_a1(efx);
++
++ /* Schedule processing of any interrupting queues */
++ channel = &efx->channel[0];
++ while (queues) {
++ if (queues & 0x01)
++ efx_schedule_channel(channel);
++ channel++;
++ queues >>= 1;
++ }
++
++ return IRQ_HANDLED;
++}
++
++/* Handle an MSI interrupt from Falcon
++ *
++ * Handle an MSI hardware interrupt. This routine schedules event
++ * queue processing. No interrupt acknowledgement cycle is necessary.
++ * Also, we never need to check that the interrupt is for us, since
++ * MSI interrupts cannot be shared.
++ *
++ * This routine must guarantee not to touch the hardware when
++ * interrupts are disabled, to allow for correct semantics of
++ * efx_suspend() and efx_resume().
++ */
++#if !defined(EFX_HAVE_IRQ_HANDLER_REGS)
++static irqreturn_t falcon_msi_interrupt(int irq, void *dev_id)
++#else
++static irqreturn_t falcon_msi_interrupt(int irq, void *dev_id,
++ struct pt_regs *regs
++ __attribute__ ((unused)))
++#endif
++{
++ struct efx_channel *channel = (struct efx_channel *)dev_id;
++ struct efx_nic *efx = channel->efx;
++ efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr;
++ int syserr;
++
++ efx->last_irq_cpu = raw_smp_processor_id();
++ EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
++ irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
++
++ /* Check to see if we have a serious error condition */
++ syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT);
++ if (unlikely(syserr))
++ return falcon_fatal_interrupt(efx);
++
++ /* Schedule processing of the channel */
++ efx_schedule_channel(channel);
++
++ return IRQ_HANDLED;
++}
++
++
++/* Setup RSS indirection table.
++ * This maps from the hash value of the packet to RXQ
++ */
++static void falcon_setup_rss_indir_table(struct efx_nic *efx)
++{
++ int i = 0;
++ unsigned long offset;
++ unsigned long flags __attribute__ ((unused));
++ efx_dword_t dword;
++
++ if (FALCON_REV(efx) < FALCON_REV_B0)
++ return;
++
++ for (offset = RX_RSS_INDIR_TBL_B0;
++ offset < RX_RSS_INDIR_TBL_B0 + 0x800;
++ offset += 0x10) {
++ EFX_POPULATE_DWORD_1(dword, RX_RSS_INDIR_ENT_B0,
++ i % efx->rss_queues);
++ falcon_writel(efx, &dword, offset);
++ i++;
++ }
++}
++
++/* Hook interrupt handler(s)
++ * Try MSI and then legacy interrupts.
++ */
++int falcon_init_interrupt(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ int rc;
++
++ if (!EFX_INT_MODE_USE_MSI(efx)) {
++ irq_handler_t handler;
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ handler = falcon_legacy_interrupt_b0;
++ else
++ handler = falcon_legacy_interrupt_a1;
++
++ rc = request_irq(efx->legacy_irq, handler, IRQF_SHARED,
++ efx->name, efx);
++ if (rc) {
++ EFX_ERR(efx, "failed to hook legacy IRQ %d\n",
++ efx->pci_dev->irq);
++ goto fail1;
++ }
++ return 0;
++ }
++
++ /* Hook MSI or MSI-X interrupt */
++ efx_for_each_channel_with_interrupt(channel, efx) {
++ rc = request_irq(channel->irq, falcon_msi_interrupt,
++ IRQF_PROBE_SHARED, /* Not shared */
++ efx->name, channel);
++ if (rc) {
++ EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq);
++ goto fail2;
++ }
++ }
++
++ return 0;
++
++ fail2:
++ efx_for_each_channel_with_interrupt(channel, efx)
++ free_irq(channel->irq, channel);
++ fail1:
++ return rc;
++}
++
++void falcon_fini_interrupt(struct efx_nic *efx)
++{
++ struct efx_channel *channel;
++ efx_oword_t reg;
++
++ /* Disable MSI/MSI-X interrupts */
++ efx_for_each_channel_with_interrupt(channel, efx)
++ if (channel->irq)
++ free_irq(channel->irq, channel);
++
++ /* ACK legacy interrupt */
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ falcon_read(efx, &reg, INT_ISR0_B0);
++ else
++ falcon_irq_ack_a1(efx);
++
++ /* Disable legacy interrupt */
++ if (efx->legacy_irq)
++ free_irq(efx->legacy_irq, efx);
++}
++
++/**************************************************************************
++ *
++ * EEPROM/flash
++ *
++ **************************************************************************
++ */
++
++/* Wait for SPI command completion */
++static int falcon_spi_wait(struct efx_nic *efx)
++{
++ efx_oword_t reg;
++ int cmd_en, timer_active;
++ int count;
++
++ count = 0;
++ do {
++ falcon_read(efx, &reg, EE_SPI_HCMD_REG_KER);
++ cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN);
++ timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE);
++ if (!cmd_en && !timer_active)
++ return 0;
++ udelay(10);
++ } while (++count < 10000); /* wait upto 100msec */
++ EFX_ERR(efx, "timed out waiting for SPI\n");
++ return -ETIMEDOUT;
++}
++
++static int
++falcon_spi_read(const struct efx_spi_device *spi, struct efx_nic *efx,
++ unsigned int command, int address, void *data, unsigned int len)
++{
++ int addressed = (address >= 0);
++ efx_oword_t reg;
++ int rc;
++
++ /* Input validation */
++ if (len > FALCON_SPI_MAX_LEN)
++ return -EINVAL;
++
++ /* Acquire SPI lock */
++ mutex_lock(&efx->spi_lock);
++
++ /* Check SPI not currently being accessed */
++ rc = falcon_spi_wait(efx);
++ if (rc)
++ goto out;
++
++ /* Program address register, if we have an address */
++ if (addressed) {
++ EFX_POPULATE_OWORD_1(reg, EE_SPI_HADR_ADR, address);
++ falcon_write(efx, &reg, EE_SPI_HADR_REG_KER);
++ }
++
++ /* Issue read command */
++ EFX_POPULATE_OWORD_7(reg,
++ EE_SPI_HCMD_CMD_EN, 1,
++ EE_SPI_HCMD_SF_SEL, spi->device_id,
++ EE_SPI_HCMD_DABCNT, len,
++ EE_SPI_HCMD_READ, EE_SPI_READ,
++ EE_SPI_HCMD_DUBCNT, 0,
++ EE_SPI_HCMD_ADBCNT,
++ (addressed ? spi->addr_len : 0),
++ EE_SPI_HCMD_ENC, command);
++ falcon_write(efx, &reg, EE_SPI_HCMD_REG_KER);
++
++ /* Wait for read to complete */
++ rc = falcon_spi_wait(efx);
++ if (rc)
++ goto out;
++
++ /* Read data */
++ falcon_read(efx, &reg, EE_SPI_HDATA_REG_KER);
++ memcpy(data, &reg, len);
++
++ out:
++ /* Release SPI lock */
++ mutex_unlock(&efx->spi_lock);
++
++ return rc;
++}
++
++static int
++falcon_spi_write(const struct efx_spi_device *spi, struct efx_nic *efx,
++ unsigned int command, int address, const void *data,
++ unsigned int len)
++{
++ int addressed = (address >= 0);
++ efx_oword_t reg;
++ int rc;
++
++ /* Input validation */
++ if (len > (addressed ? efx_spi_write_limit(spi, address)
++ : FALCON_SPI_MAX_LEN))
++ return -EINVAL;
++
++ /* Acquire SPI lock */
++ mutex_lock(&efx->spi_lock);
++
++ /* Check SPI not currently being accessed */
++ rc = falcon_spi_wait(efx);
++ if (rc)
++ goto out;
++
++ /* Program address register, if we have an address */
++ if (addressed) {
++ EFX_POPULATE_OWORD_1(reg, EE_SPI_HADR_ADR, address);
++ falcon_write(efx, &reg, EE_SPI_HADR_REG_KER);
++ }
++
++ /* Program data register, if we have data */
++ if (data) {
++ memcpy(&reg, data, len);
++ falcon_write(efx, &reg, EE_SPI_HDATA_REG_KER);
++ }
++
++ /* Issue write command */
++ EFX_POPULATE_OWORD_7(reg,
++ EE_SPI_HCMD_CMD_EN, 1,
++ EE_SPI_HCMD_SF_SEL, spi->device_id,
++ EE_SPI_HCMD_DABCNT, len,
++ EE_SPI_HCMD_READ, EE_SPI_WRITE,
++ EE_SPI_HCMD_DUBCNT, 0,
++ EE_SPI_HCMD_ADBCNT,
++ (addressed ? spi->addr_len : 0),
++ EE_SPI_HCMD_ENC, command);
++ falcon_write(efx, &reg, EE_SPI_HCMD_REG_KER);
++
++ /* Wait for write to complete */
++ rc = falcon_spi_wait(efx);
++ if (rc)
++ goto out;
++
++ out:
++ /* Release SPI lock */
++ mutex_unlock(&efx->spi_lock);
++
++ return rc;
++}
++
++/**************************************************************************
++ *
++ * MAC wrapper
++ *
++ **************************************************************************
++ */
++void falcon_drain_tx_fifo(struct efx_nic *efx)
++{
++ efx_oword_t temp;
++ efx_oword_t mcast_reg0;
++ efx_oword_t mcast_reg1;
++ int count;
++
++ if (FALCON_REV(efx) < FALCON_REV_B0)
++ return;
++
++ falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
++ /* There is no point in draining more than once */
++ if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0))
++ return;
++
++ /* MAC stats will fail whilst the TX fifo is draining. Serialise
++ * the drain sequence with the statistics fetch */
++ spin_lock(&efx->stats_lock);
++
++ EFX_SET_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0, 1);
++ falcon_write(efx, &temp, MAC0_CTRL_REG_KER);
++
++ falcon_read(efx, &mcast_reg0, MAC_MCAST_HASH_REG0_KER);
++ falcon_read(efx, &mcast_reg1, MAC_MCAST_HASH_REG1_KER);
++
++ /* Reset the MAC and EM block. */
++ falcon_read(efx, &temp, GLB_CTL_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, RST_XGTX, 1);
++ EFX_SET_OWORD_FIELD(temp, RST_XGRX, 1);
++ EFX_SET_OWORD_FIELD(temp, RST_EM, 1);
++ falcon_write(efx, &temp, GLB_CTL_REG_KER);
++
++ count = 0;
++ while (1) {
++ falcon_read(efx, &temp, GLB_CTL_REG_KER);
++ if (!EFX_OWORD_FIELD(temp, RST_XGTX) &&
++ !EFX_OWORD_FIELD(temp, RST_XGRX) &&
++ !EFX_OWORD_FIELD(temp, RST_EM)) {
++ EFX_LOG(efx, "Completed MAC reset after %d loops\n",
++ count);
++ break;
++ }
++ if (count > 20) {
++ EFX_ERR(efx, "MAC reset failed\n");
++ break;
++ }
++ count++;
++ udelay(10);
++ }
++
++ spin_unlock(&efx->stats_lock);
++
++ /* Restore the multicast hash registers. */
++ falcon_write(efx, &mcast_reg0, MAC_MCAST_HASH_REG0_KER);
++ falcon_write(efx, &mcast_reg1, MAC_MCAST_HASH_REG1_KER);
++
++ /* If we've reset the EM block and the link is up, then
++ * we'll have to kick the XAUI link so the PHY can recover */
++ if (efx->link_up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx))
++ falcon_reset_xaui(efx);
++}
++
++void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
++{
++ struct falcon_nic_data *nic_data = efx->nic_data;
++ efx_oword_t temp;
++ int changing_loopback;
++
++ if (FALCON_REV(efx) < FALCON_REV_B0)
++ return;
++
++ /* Isolate the MAC -> RX */
++ falcon_read(efx, &temp, RX_CFG_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 0);
++ falcon_write(efx, &temp, RX_CFG_REG_KER);
++
++ /* Synchronise the EM block against any loopback mode changes by
++ * draining the TX fifo and resetting. */
++ changing_loopback = (efx->loopback_mode != nic_data->old_loopback_mode);
++ nic_data->old_loopback_mode = efx->loopback_mode;
++ if (changing_loopback || !efx->link_up)
++ falcon_drain_tx_fifo(efx);
++}
++
++void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
++{
++ efx_oword_t reg;
++ int link_speed;
++ unsigned int tx_fc;
++
++ if (efx->link_options & GM_LPA_10000)
++ link_speed = 0x3;
++ else if (efx->link_options & GM_LPA_1000)
++ link_speed = 0x2;
++ else if (efx->link_options & GM_LPA_100)
++ link_speed = 0x1;
++ else
++ link_speed = 0x0;
++ /* MAC_LINK_STATUS controls MAC backpressure but doesn't work
++ * as advertised. Disable to ensure packets are not
++ * indefinitely held and TX queue can be flushed at any point
++ * while the link is down.
++ */
++ EFX_POPULATE_OWORD_5(reg,
++ MAC_XOFF_VAL, 0xffff /* max pause time */,
++ MAC_BCAD_ACPT, 1,
++ MAC_UC_PROM, efx->promiscuous,
++ MAC_LINK_STATUS, 1, /* always set */
++ MAC_SPEED, link_speed);
++ /* On B0, MAC backpressure can be disabled and packets get
++ * discarded. */
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0,
++ !efx->link_up);
++ }
++
++ falcon_write(efx, &reg, MAC0_CTRL_REG_KER);
++
++ /*
++ * Transmission of pause frames when RX crosses the threshold is
++ * covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
++ *
++ * Action on receipt of pause frames is controller by XM_DIS_FCNTL
++ */
++ tx_fc = (efx->flow_control & EFX_FC_TX) ? 1 : 0;
++ falcon_read(efx, &reg, RX_CFG_REG_KER);
++ EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
++
++ /* Unisolate the MAC -> RX */
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 1);
++ falcon_write(efx, &reg, RX_CFG_REG_KER);
++}
++
++int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
++{
++ efx_oword_t reg;
++ u32 *dma_done;
++ int i;
++
++ if (disable_dma_stats)
++ return 0;
++
++ /* Statistics fetch will fail if the MAC is in TX drain */
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ efx_oword_t temp;
++ falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
++ if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0))
++ return 0;
++ }
++
++ /* Clear completion pointer */
++ dma_done = (efx->stats_buffer.addr + done_offset);
++ *dma_done = FALCON_STATS_NOT_DONE;
++ wmb(); /* ensure done flag is clear */
++
++ /* Initiate DMA transfer of stats */
++ EFX_POPULATE_OWORD_2(reg,
++ MAC_STAT_DMA_CMD, 1,
++ MAC_STAT_DMA_ADR,
++ efx->stats_buffer.dma_addr);
++ falcon_write(efx, &reg, MAC0_STAT_DMA_REG_KER);
++
++ /* Wait for transfer to complete */
++ for (i = 0; i < 400; i++) {
++ if (*(volatile u32 *)dma_done == FALCON_STATS_DONE)
++ return 0;
++ udelay(10);
++ }
++
++ if (EFX_WORKAROUND_8419(efx)) {
++ disable_dma_stats = 1;
++ EFX_INFO(efx, "MAC stats DMA disabled\n");
++ } else {
++ EFX_ERR(efx, "timed out waiting for statistics\n");
++ }
++
++ return -ETIMEDOUT;
++}
++
++/**************************************************************************
++ *
++ * PHY access via GMII
++ *
++ **************************************************************************
++ */
++
++/* Use the top bit of the MII PHY id to indicate the PHY type
++ * (1G/10G), with the remaining bits as the actual PHY id.
++ *
++ * This allows us to avoid leaking information from the mii_if_info
++ * structure into other data structures.
++ */
++#define FALCON_PHY_ID_ID_WIDTH EFX_WIDTH(MD_PRT_DEV_ADR)
++#define FALCON_PHY_ID_ID_MASK ((1 << FALCON_PHY_ID_ID_WIDTH) - 1)
++#define FALCON_PHY_ID_WIDTH (FALCON_PHY_ID_ID_WIDTH + 1)
++#define FALCON_PHY_ID_MASK ((1 << FALCON_PHY_ID_WIDTH) - 1)
++#define FALCON_PHY_ID_10G (1 << (FALCON_PHY_ID_WIDTH - 1))
++
++
++/* Packing the clause 45 port and device fields into a single value */
++#define MD_PRT_ADR_COMP_LBN (MD_PRT_ADR_LBN - MD_DEV_ADR_LBN)
++#define MD_PRT_ADR_COMP_WIDTH MD_PRT_ADR_WIDTH
++#define MD_DEV_ADR_COMP_LBN 0
++#define MD_DEV_ADR_COMP_WIDTH MD_DEV_ADR_WIDTH
++
++
++/* Wait for GMII access to complete */
++static int falcon_gmii_wait(struct efx_nic *efx)
++{
++ efx_dword_t md_stat;
++ int count;
++
++ for (count = 0; count < 1000; count++) { /* wait upto 10ms */
++ falcon_readl(efx, &md_stat, MD_STAT_REG_KER);
++ if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) {
++ if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 ||
++ EFX_DWORD_FIELD(md_stat, MD_BSERR) != 0) {
++ EFX_ERR(efx, "error from GMII access "
++ EFX_DWORD_FMT"\n",
++ EFX_DWORD_VAL(md_stat));
++ return -EIO;
++ }
++ return 0;
++ }
++ udelay(10);
++ }
++ EFX_ERR(efx, "timed out waiting for GMII\n");
++ return -ETIMEDOUT;
++}
++
++/* Writes a GMII register of a PHY connected to Falcon using MDIO. */
++static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
++ int addr, int value)
++{
++ struct efx_nic *efx = (struct efx_nic *)net_dev->priv;
++ unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK;
++ unsigned int phy_10g = phy_id & FALCON_PHY_ID_10G;
++ efx_oword_t reg;
++
++ /* The 'generic' prt/dev packing in mdio_10g.h is conveniently
++ * chosen so that the only current user, Falcon, can take the
++ * packed value and use them directly.
++ * Fail to build if this assumption is broken.
++ */
++ BUILD_BUG_ON(FALCON_PHY_ID_10G != MDIO45_XPRT_ID_IS10G);
++ BUILD_BUG_ON(FALCON_PHY_ID_ID_WIDTH != MDIO45_PRT_DEV_WIDTH);
++ BUILD_BUG_ON(MD_PRT_ADR_COMP_LBN != MDIO45_PRT_ID_COMP_LBN);
++ BUILD_BUG_ON(MD_DEV_ADR_COMP_LBN != MDIO45_DEV_ID_COMP_LBN);
++
++ if (phy_id2 == PHY_ADDR_INVALID)
++ return;
++
++ /* See falcon_mdio_read for an explanation. */
++ if (EFX_ISCLAUSE45(efx) && !phy_10g) {
++ int mmd = ffs(efx->phy_op->mmds) - 1;
++ EFX_TRACE(efx, "Fixing erroneous clause22 write\n");
++ phy_id2 = mdio_clause45_pack(phy_id2, mmd)
++ & FALCON_PHY_ID_ID_MASK;
++ phy_10g = 1;
++ }
++
++ EFX_REGDUMP(efx, "writing GMII %d register %02x with %04x\n", phy_id,
++ addr, value);
++
++ /* Obtain PHY lock */
++ spin_lock_bh(&efx->phy_lock);
++
++ /* Check MII not currently being accessed */
++ if (falcon_gmii_wait(efx) != 0)
++ goto out;
++
++ /* Write the address/ID register */
++ EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
++ falcon_write(efx, &reg, MD_PHY_ADR_REG_KER);
++
++ if (phy_10g)
++ EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_id2);
++ else
++ /* MDIO clause 22 */
++ EFX_POPULATE_OWORD_2(reg,
++ MD_PRT_ADR, phy_id2,
++ MD_DEV_ADR, addr);
++ falcon_write(efx, &reg, MD_ID_REG_KER);
++
++ /* Write data */
++ EFX_POPULATE_OWORD_1(reg, MD_TXD, value);
++ falcon_write(efx, &reg, MD_TXD_REG_KER);
++
++ EFX_POPULATE_OWORD_2(reg,
++ MD_WRC, 1,
++ MD_GC, (phy_10g ? 0 : 1));
++ falcon_write(efx, &reg, MD_CS_REG_KER);
++
++ /* Wait for data to be written */
++ if (falcon_gmii_wait(efx) != 0) {
++ /* Abort the write operation */
++ EFX_POPULATE_OWORD_2(reg,
++ MD_WRC, 0,
++ MD_GC, 1);
++ falcon_write(efx, &reg, MD_CS_REG_KER);
++ udelay(10);
++ }
++
++ out:
++ /* Release PHY lock */
++ spin_unlock_bh(&efx->phy_lock);
++}
++
++/* Reads a GMII register from a PHY connected to Falcon. If no value
++ * could be read, -1 will be returned. */
++static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr)
++{
++ struct efx_nic *efx = (struct efx_nic *)net_dev->priv;
++ unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK;
++ unsigned int phy_10g = phy_id & FALCON_PHY_ID_10G;
++ efx_oword_t reg;
++ int value = -1;
++ unsigned long flags __attribute__ ((unused));
++
++ if (phy_addr == PHY_ADDR_INVALID)
++ return -1;
++
++ /* Our PHY code knows whether it needs to talk clause 22(1G) or 45(10G)
++ * but the generic Linux code does not make any distinction or have
++ * any state for this.
++ * We spot the case where someone tried to talk 22 to a 45 PHY and
++ * redirect the request to the lowest numbered MMD as a clause45
++ * request. This is enough to allow simple queries like id and link
++ * state to succeed. TODO: We may need to do more in future.
++ */
++ if (EFX_ISCLAUSE45(efx) && !phy_10g) {
++ int mmd = ffs(efx->phy_op->mmds) - 1;
++ EFX_TRACE(efx, "Fixing erroneous clause22 read\n");
++ phy_addr = mdio_clause45_pack(phy_addr, mmd)
++ & FALCON_PHY_ID_ID_MASK;
++ phy_10g = 1;
++ }
++
++ /* Obtain PHY lock */
++ spin_lock_bh(&efx->phy_lock);
++
++ /* Check MII not currently being accessed */
++ if (falcon_gmii_wait(efx) != 0)
++ goto out;
++
++ if (!phy_10g) {
++ /* Write the address registers */
++ EFX_POPULATE_OWORD_2(reg,
++ MD_PRT_ADR, phy_addr,
++ MD_DEV_ADR, addr);
++ falcon_write(efx, &reg, MD_ID_REG_KER);
++ /* Request data to be read */
++ EFX_POPULATE_OWORD_2(reg,
++ MD_RIC, 1,
++ MD_GC, 1);
++ } else {
++ EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
++ falcon_write(efx, &reg, MD_PHY_ADR_REG_KER);
++
++ EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_addr);
++ falcon_write(efx, &reg, MD_ID_REG_KER);
++
++ /* Request data to be read */
++ EFX_POPULATE_OWORD_2(reg,
++ MD_RDC, 1,
++ MD_GC, 0);
++ }
++ falcon_write(efx, &reg, MD_CS_REG_KER);
++
++ /* Wait for data to become available */
++ value = falcon_gmii_wait(efx);
++ if (value == 0) {
++ falcon_read(efx, &reg, MD_RXD_REG_KER);
++ value = EFX_OWORD_FIELD(reg, MD_RXD);
++ EFX_REGDUMP(efx, "read from GMII %d register %02x, got %04x\n",
++ phy_id, addr, value);
++ } else {
++ /* Abort the read operation */
++ EFX_POPULATE_OWORD_2(reg,
++ MD_RIC, 0,
++ MD_GC, 1);
++ falcon_write(efx, &reg, MD_CS_REG_KER);
++
++ EFX_LOG(efx, "read from GMII 0x%x register %02x, got "
++ "error %d\n", phy_id, addr, value);
++ }
++
++ out:
++ /* Release PHY lock */
++ spin_unlock_bh(&efx->phy_lock);
++
++ return value;
++}
++
++static void falcon_init_mdio(struct mii_if_info *gmii)
++{
++ gmii->mdio_read = falcon_mdio_read;
++ gmii->mdio_write = falcon_mdio_write;
++ gmii->phy_id_mask = FALCON_PHY_ID_MASK;
++ gmii->reg_num_mask = ((1 << EFX_WIDTH(MD_DEV_ADR)) - 1);
++}
++
++static int falcon_probe_gmac_port(struct efx_nic *efx)
++{
++ struct efx_phy_operations *phy_op = efx->phy_op;
++
++ efx->mac_op = &falcon_gmac_operations;
++ efx->loopback_modes = LOOPBACKS_1G_INTERNAL | phy_op->loopbacks;
++ efx->startup_loopbacks = ((1 << LOOPBACK_MAC) |
++ (1 << phy_op->startup_loopback));
++ return 0;
++}
++
++static int falcon_probe_xmac_port(struct efx_nic *efx)
++{
++ struct efx_phy_operations *phy_op = efx->phy_op;
++
++ efx->mac_op = &falcon_xmac_operations;
++
++ /* The Falcon B0 FPGA only supports XGMII loopback */
++ if (FALCON_REV(efx) >= FALCON_REV_B0 && !efx->is_asic)
++ efx->loopback_modes = (1 << LOOPBACK_XGMII);
++ else
++ efx->loopback_modes = LOOPBACKS_10G_INTERNAL;
++ efx->loopback_modes |= phy_op->loopbacks;
++
++ efx->startup_loopbacks = ((1 << LOOPBACK_XGMII) |
++ (1 << phy_op->startup_loopback));
++ return 0;
++}
++
++static int falcon_probe_phy(struct efx_nic *efx)
++{
++ switch (efx->phy_type) {
++ case PHY_TYPE_1G_ALASKA:
++ efx->phy_op = &alaska_phy_operations;
++ break;
++ case PHY_TYPE_10XPRESS:
++ efx->phy_op = &falcon_tenxpress_phy_ops;
++ break;
++ case PHY_TYPE_NONE:
++ efx->phy_op = &falcon_null_phy_ops;
++ break;
++ case PHY_TYPE_XFP:
++ efx->phy_op = &falcon_xfp_phy_ops;
++ break;
++ case PHY_TYPE_CX4_RTMR:
++ efx->phy_op = &falcon_txc_phy_ops;
++ break;
++ case PHY_TYPE_PM8358:
++ efx->phy_op = &falcon_pm8358_phy_ops;
++ break;
++ default:
++ EFX_ERR(efx, "Unknown PHY type %d\n",
++ efx->phy_type);
++ return -1;
++ }
++ return 0;
++}
++
++/* This call is responsible for hooking in the MAC and PHY operations */
++int falcon_probe_port(struct efx_nic *efx)
++{
++ int rc;
++
++ /* Hook in PHY operations table */
++ rc = falcon_probe_phy(efx);
++ if (rc)
++ return rc;
++
++ /* Hook in MAC operations table */
++ if (EFX_IS10G(efx))
++ rc = falcon_probe_xmac_port(efx);
++ else
++ rc = falcon_probe_gmac_port(efx);
++ if (rc)
++ return rc;
++
++ EFX_LOG(efx, "created port using %cMAC\n",
++ EFX_IS10G(efx) ? 'X' : 'G');
++
++ /* Set up GMII structure for PHY */
++ efx->mii.supports_gmii = 1;
++ falcon_init_mdio(&efx->mii);
++
++ /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ efx->flow_control = EFX_FC_RX | EFX_FC_TX;
++ else
++ efx->flow_control = EFX_FC_RX;
++
++ /* Allocate buffer for stats */
++ rc = falcon_alloc_buffer(efx, &efx->stats_buffer,
++ FALCON_MAC_STATS_SIZE);
++ if (rc)
++ return rc;
++ EFX_LOG(efx, "stats buffer at %llx (virt %p phys %lx)\n",
++ (unsigned long long)efx->stats_buffer.dma_addr,
++ efx->stats_buffer.addr,
++ virt_to_phys(efx->stats_buffer.addr));
++
++ return 0;
++}
++
++void falcon_remove_port(struct efx_nic *efx)
++{
++ /* Free stats buffer */
++ falcon_free_buffer(efx, &efx->stats_buffer);
++}
++
++/**************************************************************************
++ *
++ * Multicast filtering
++ *
++ **************************************************************************
++ */
++
++void falcon_set_multicast_hash(struct efx_nic *efx)
++{
++ union efx_multicast_hash falcon_mc_hash;
++
++ /* Broadcast packets go through the multicast hash filter.
++ * ether_crc_le() of the broadcast address is 0xbe2612ff
++ * so we always add bit 0xff to the mask we are given.
++ */
++ memcpy(&falcon_mc_hash, &efx->multicast_hash, sizeof(falcon_mc_hash));
++ set_bit_le(0xff, (void *)&falcon_mc_hash);
++
++ falcon_write(efx, &falcon_mc_hash.oword[0], MAC_MCAST_HASH_REG0_KER);
++ falcon_write(efx, &falcon_mc_hash.oword[1], MAC_MCAST_HASH_REG1_KER);
++}
++
++/**************************************************************************
++ *
++ * Device reset
++ *
++ **************************************************************************
++ */
++
++static int falcon_clear_b0_memories(struct efx_nic *efx)
++{
++ /* Need to clear memories after a reset. On B0 we can do this
++ * via the net function.
++ */
++ int rc = 0, offset;
++ efx_oword_t blanko;
++ efx_dword_t blankd;
++ unsigned long membase_phys, membase_len;
++ void __iomem *membase_orig;
++ unsigned long flags __attribute__ ((unused));
++
++ EFX_ZERO_OWORD(blanko);
++ EFX_ZERO_DWORD(blankd);
++ membase_orig = efx->membase;
++ membase_phys = pci_resource_start(efx->pci_dev, efx->type->mem_bar);
++
++ for (offset = RX_FILTER_TBL0;
++ offset < RX_RSS_INDIR_TBL_B0;
++ offset += 0x10)
++ falcon_write(efx, &blanko, offset);
++
++ /* Clear RSS indirection table */
++ for (offset = RX_RSS_INDIR_TBL_B0;
++ offset < RX_RSS_INDIR_TBL_B0 + 0x800;
++ offset += 0x10)
++ /* Clear 6 bits every 16 bytes */
++ falcon_writel(efx, &blankd, offset);
++
++ /* Need to split this into several mappings so MSI-X table and PBA
++ * never get mapped
++ */
++ membase_phys = membase_phys + 0x2800000;
++ membase_len = 0x3000000 - 0x2800000;
++
++ efx->membase = ioremap_nocache(membase_phys, membase_len);
++ if (efx->membase == NULL) {
++ EFX_ERR(efx, "could not map memory BAR %d at %lx+%lx\n",
++ efx->type->mem_bar, membase_phys, membase_len);
++ rc = -ENOMEM;
++ goto out;
++ }
++ /* Clear the buffer table. The first 7/8 of it is a duplicate
++ * of the mapping at 0x800000 and must be accessed 2 DWORDs at
++ * a time. The final 1/8 must be accessed 4 DWORDs at a time.
++ * We make sure to obey both rules at the same time.
++ */
++ for (offset = 0; offset < membase_len; offset += 0x10) {
++ spin_lock_irqsave(&efx->biu_lock, flags);
++ _falcon_writel(efx, 0, offset + 0x0);
++ wmb();
++ _falcon_writel(efx, 0, offset + 0x4);
++ wmb();
++ _falcon_writel(efx, 0, offset + 0x8);
++ wmb();
++ _falcon_writel(efx, 0, offset + 0xc);
++ mmiowb();
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++ }
++
++ iounmap(efx->membase);
++
++out:
++ /* Restore */
++ efx->membase = membase_orig;
++
++ return rc;
++}
++
++
++/* Resets NIC to known state. This routine must be called in process
++ * context and is allowed to sleep. */
++int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
++{
++ efx_oword_t glb_ctl_reg_ker;
++ int rc;
++
++ EFX_LOG(efx, "performing %s hardware reset\n", RESET_TYPE(method));
++
++ /* Initiate device reset */
++ if (method == RESET_TYPE_WORLD) {
++ /* Save PCI config space */
++ rc = pci_save_state(efx->pci_dev);
++ if (rc) {
++ EFX_ERR(efx, "failed to backup PCI state of primary "
++ "function prior to hardware reset\n");
++ goto fail1;
++ }
++ if (efx->type->is_dual_func) {
++ rc = pci_save_state(efx->pci_dev2);
++ if (rc) {
++ EFX_ERR(efx, "failed to backup PCI state of "
++ "secondary function prior to "
++ "hardware reset\n");
++ goto fail2;
++ }
++ }
++
++ EFX_POPULATE_OWORD_2(glb_ctl_reg_ker,
++ EXT_PHY_RST_DUR, 0x7,
++ SWRST, 1);
++ } else {
++ int reset_phy = (method == RESET_TYPE_INVISIBLE ?
++ EXCLUDE_FROM_RESET : 0);
++
++ EFX_POPULATE_OWORD_7(glb_ctl_reg_ker,
++ EXT_PHY_RST_CTL, reset_phy,
++ PCIE_CORE_RST_CTL, EXCLUDE_FROM_RESET,
++ PCIE_NSTCK_RST_CTL, EXCLUDE_FROM_RESET,
++ PCIE_SD_RST_CTL, EXCLUDE_FROM_RESET,
++ EE_RST_CTL, EXCLUDE_FROM_RESET,
++ EXT_PHY_RST_DUR, 0x7 /* 10ms */,
++ SWRST, 1);
++ }
++ falcon_write(efx, &glb_ctl_reg_ker, GLB_CTL_REG_KER);
++
++ /* Wait for 50ms for the chip to come out of reset */
++ EFX_LOG(efx, "waiting for hardware reset\n");
++ schedule_timeout_uninterruptible(HZ / 20);
++
++ /* Restore PCI configuration if needed */
++ if (method == RESET_TYPE_WORLD) {
++ if (efx->type->is_dual_func) {
++ rc = pci_restore_state(efx->pci_dev2);
++ if (rc) {
++ EFX_ERR(efx, "failed to restore PCI config for "
++ "the secondary function\n");
++ goto fail3;
++ }
++ }
++ rc = pci_restore_state(efx->pci_dev);
++ if (rc) {
++ EFX_ERR(efx, "failed to restore PCI config for the "
++ "primary function\n");
++ goto fail4;
++ }
++ EFX_LOG(efx, "successfully restored PCI config\n");
++ }
++
++ /* Assert that reset complete */
++ falcon_read(efx, &glb_ctl_reg_ker, GLB_CTL_REG_KER);
++ if (EFX_OWORD_FIELD(glb_ctl_reg_ker, SWRST) != 0) {
++ rc = -ETIMEDOUT;
++ EFX_ERR(efx, "timed out waiting for hardware reset\n");
++ goto fail5;
++ }
++ EFX_LOG(efx, "hardware reset complete\n");
++
++ if (EFX_WORKAROUND_8202(efx)) {
++ rc = falcon_clear_b0_memories(efx);
++ if (rc)
++ goto fail6;
++ }
++
++ return 0;
++
++ /* pci_save_state() and pci_restore_state() MUST be called in pairs */
++fail2:
++fail3:
++ pci_restore_state(efx->pci_dev);
++ /* fall-thru */
++fail1:
++fail4:
++fail5:
++fail6:
++ return rc;
++}
++
++/* Zeroes out the SRAM contents. This routine must be called in
++ * process context and is allowed to sleep.
++ */
++static int falcon_reset_sram(struct efx_nic *efx)
++{
++ efx_oword_t srm_cfg_reg_ker, gpio_cfg_reg_ker;
++ int count, onchip, sram_cfg_val;
++
++ /* Set the SRAM wake/sleep GPIO appropriately. */
++ onchip = (efx->external_sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY);
++ falcon_read(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER);
++ EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OEN, 1);
++ EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OUT, onchip ? 1 : 0);
++ falcon_write(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER);
++
++ /* Initiate SRAM reset */
++ sram_cfg_val = (efx->external_sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY) ?
++ 0 : efx->external_sram_cfg;
++
++ EFX_POPULATE_OWORD_2(srm_cfg_reg_ker,
++ SRAM_OOB_BT_INIT_EN, 1,
++ SRM_NUM_BANKS_AND_BANK_SIZE, sram_cfg_val);
++ falcon_write(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER);
++
++ /* Wait for SRAM reset to complete */
++ count = 0;
++ do {
++ EFX_LOG(efx, "waiting for SRAM reset (attempt %d)...\n", count);
++
++ /* SRAM reset is slow; expect around 16ms */
++ schedule_timeout_uninterruptible(HZ / 50);
++
++ /* Check for reset complete */
++ falcon_read(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER);
++ if (!EFX_OWORD_FIELD(srm_cfg_reg_ker, SRAM_OOB_BT_INIT_EN)) {
++ EFX_LOG(efx, "SRAM reset complete\n");
++
++ return 0;
++ }
++ } while (++count < 20); /* wait upto 0.4 sec */
++
++ EFX_ERR(efx, "timed out waiting for SRAM reset\n");
++ return -ETIMEDOUT;
++}
++
++static void falcon_spi_device_init(struct efx_spi_device **spi_device_ret,
++ unsigned int device_id, u32 device_type)
++{
++ struct efx_spi_device *spi_device;
++
++ if (device_type != 0) {
++ spi_device = kmalloc(sizeof(*spi_device), GFP_KERNEL);
++ spi_device->device_id = device_id;
++ spi_device->size =
++ 1 << SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_SIZE);
++ spi_device->addr_len =
++ SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN);
++ spi_device->munge_address = (spi_device->size == 1 << 9 &&
++ spi_device->addr_len == 1);
++ spi_device->erase_command =
++ SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ERASE_CMD);
++ spi_device->erase_size =
++ 1 << SPI_DEV_TYPE_FIELD(device_type,
++ SPI_DEV_TYPE_ERASE_SIZE);
++ spi_device->block_size =
++ 1 << SPI_DEV_TYPE_FIELD(device_type,
++ SPI_DEV_TYPE_BLOCK_SIZE);
++ spi_device->read = falcon_spi_read;
++ spi_device->write = falcon_spi_write;
++ } else {
++ spi_device = NULL;
++ }
++
++ kfree(*spi_device_ret);
++ *spi_device_ret = spi_device;
++}
++
++/* Extract non-volatile configuration */
++static int falcon_probe_nvconfig(struct efx_nic *efx)
++{
++ int rc;
++ struct falcon_nvconfig *nvconfig;
++ struct efx_spi_device *spi;
++ size_t offset, len;
++ int magic_num, struct_ver, board_rev, onchip_sram;
++
++ nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL);
++
++ /* Read the whole configuration structure into memory. It's
++ * in Falcon's boot device, which may be either flash or
++ * EEPROM, but if both are present Falcon prefers flash. The
++ * boot device is always too large for 9-bit addressing, so we
++ * don't have to munge commands.
++ */
++ spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
++ for (offset = 0; offset < sizeof(*nvconfig); offset += len) {
++ len = min(sizeof(*nvconfig) - offset,
++ (size_t) FALCON_SPI_MAX_LEN);
++ rc = falcon_spi_read(spi, efx, SPI_READ,
++ NVCONFIG_BASE + offset,
++ (char *)nvconfig + offset, len);
++ if (rc)
++ goto out;
++ }
++
++ /* Read the MAC addresses */
++ memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
++
++ /* Read the board configuration. */
++ magic_num = le16_to_cpu(nvconfig->board_magic_num);
++ struct_ver = le16_to_cpu(nvconfig->board_struct_ver);
++
++ if (magic_num != NVCONFIG_BOARD_MAGIC_NUM || struct_ver < 2) {
++ EFX_ERR(efx, "Non volatile memory bad magic=%x ver=%x "
++ "therefore using defaults\n", magic_num, struct_ver);
++ efx->phy_type = PHY_TYPE_NONE;
++ efx->mii.phy_id = PHY_ADDR_INVALID;
++ board_rev = 0;
++ onchip_sram = 1;
++
++ } else {
++ struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2;
++ struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3;
++
++ efx->phy_type = v2->port0_phy_type;
++ efx->mii.phy_id = v2->port0_phy_addr;
++ board_rev = le16_to_cpu(v2->board_revision);
++ onchip_sram = EFX_OWORD_FIELD(nvconfig->nic_stat_reg,
++ ONCHIP_SRAM);
++
++ if (struct_ver >= 3) {
++ __le32 fl = v3->spi_device_type[EE_SPI_FLASH];
++ __le32 ee = v3->spi_device_type[EE_SPI_EEPROM];
++ falcon_spi_device_init(&efx->spi_flash, EE_SPI_FLASH,
++ le32_to_cpu(fl));
++ falcon_spi_device_init(&efx->spi_eeprom, EE_SPI_EEPROM,
++ le32_to_cpu(ee));
++ }
++ }
++
++ EFX_LOG(efx, "PHY is %s(%d) phy_id %d\n",
++ PHY_TYPE(efx), efx->phy_type,
++ efx->mii.phy_id);
++
++ efx_set_board_info(efx, board_rev);
++
++ /* Read the SRAM configuration. The register is initialised
++ * automatically but might may been reset since boot.
++ */
++ if (onchip_sram) {
++ efx->external_sram_cfg = SRM_NB_BSZ_ONCHIP_ONLY;
++ } else {
++ efx->external_sram_cfg =
++ EFX_OWORD_FIELD(nvconfig->srm_cfg_reg,
++ SRM_NUM_BANKS_AND_BANK_SIZE);
++ WARN_ON(efx->external_sram_cfg == SRM_NB_BSZ_RESERVED);
++ /* Replace invalid setting with the smallest defaults */
++ if (efx->external_sram_cfg == SRM_NB_BSZ_DEFAULT)
++ efx->external_sram_cfg = SRM_NB_BSZ_1BANKS_2M;
++ }
++ EFX_LOG(efx, "external_sram_cfg=%d (>=0 is external)\n",
++ efx->external_sram_cfg);
++
++ out:
++ kfree(nvconfig);
++ return rc;
++}
++
++/* Looks at available SRAM resources and silicon revision, and works out
++ * how many queues we can support, and where things like descriptor caches
++ * should live. */
++static int falcon_dimension_resources(struct efx_nic *efx)
++{
++ unsigned buffer_entry_bytes, internal_dcs_entries, dcs;
++ struct falcon_nic_data *nic_data = efx->nic_data;
++ struct efx_dl_falcon_resources *res = &nic_data->resources;
++
++ /* Fill out the driverlink resource list */
++ res->hdr.type = EFX_DL_FALCON_RESOURCES;
++ res->biu_lock = &efx->biu_lock;
++ efx->dl_info = &res->hdr;
++
++ /* This is set to 16 for a good reason. In summary, if larger than
++ * 16, the descriptor cache holds more than a default socket
++ * buffer's worth of packets (for UDP we can only have at most one
++ * socket buffer's worth outstanding). This combined with the fact
++ * that we only get 1 TX event per descriptor cache means the NIC
++ * goes idle.
++ * 16 gives us up to 256 TXQs on Falcon B in internal-SRAM mode,
++ * and up to 512 on Falcon A.
++ */
++ nic_data->tx_dc_entries = 16;
++
++ /* Set the RX descriptor cache size. Values 16, 32 and 64 are
++ * supported (8 won't work). Bigger is better, especially on B
++ * silicon.
++ */
++ nic_data->rx_dc_entries = descriptor_cache_size;
++ dcs = ffs(nic_data->rx_dc_entries);
++ if ((dcs < 5) || (dcs > 7) ||
++ ((1 << (dcs - 1)) != nic_data->rx_dc_entries)) {
++ EFX_ERR(efx, "bad descriptor_cache_size=%d (dcs=%d)\n",
++ nic_data->rx_dc_entries, dcs);
++ return -EINVAL;
++ }
++
++ /* NB. The minimum values get increased as this driver initialises
++ * its resources, so this should prevent any overlap.
++ */
++ switch (FALCON_REV(efx)) {
++ case FALCON_REV_A1:
++ res->rxq_min = res->txq_min = 16;
++ res->evq_int_min = res->evq_int_max = 4;
++ res->evq_timer_min = 5;
++ res->evq_timer_max = 4096;
++ internal_dcs_entries = 8192;
++ break;
++ case FALCON_REV_B0:
++ default:
++ res->rxq_min = res->txq_min = res->evq_int_min = 0;
++ res->evq_int_max = 64;
++ res->evq_timer_min = 64;
++ res->evq_timer_max = 4096;
++ internal_dcs_entries = 4096;
++ break;
++ }
++
++ buffer_entry_bytes = 8;
++
++ if (efx->external_sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY) {
++ res->rxq_max = internal_dcs_entries / nic_data->rx_dc_entries;
++ res->txq_max = internal_dcs_entries / nic_data->tx_dc_entries;
++ /* Prog model says 8K entries for buffer table in internal
++ * mode. But does this not depend on full/half mode?
++ */
++ res->buffer_table_max = 8192;
++ nic_data->tx_dc_base = 0x130000;
++ nic_data->rx_dc_base = 0x100000;
++ } else {
++ unsigned sram_bytes, vnic_bytes, max_vnics, n_vnics;
++
++ /* Determine how much SRAM we have to play with. We have
++ * to fit buffer table and descriptor caches in.
++ */
++ switch (efx->external_sram_cfg) {
++ case SRM_NB_BSZ_1BANKS_2M:
++ default:
++ sram_bytes = 2 * 1024 * 1024;
++ break;
++ case SRM_NB_BSZ_1BANKS_4M:
++ case SRM_NB_BSZ_2BANKS_4M:
++ sram_bytes = 4 * 1024 * 1024;
++ break;
++ case SRM_NB_BSZ_1BANKS_8M:
++ case SRM_NB_BSZ_2BANKS_8M:
++ sram_bytes = 8 * 1024 * 1024;
++ break;
++ case SRM_NB_BSZ_2BANKS_16M:
++ sram_bytes = 16 * 1024 * 1024;
++ break;
++ }
++ /* For each VNIC allow at least 512 buffer table entries
++ * and descriptor cache for an rxq and txq. Buffer table
++ * space for evqs and dmaqs is relatively trivial, so not
++ * considered in this calculation.
++ */
++ vnic_bytes = (512 * buffer_entry_bytes
++ + nic_data->rx_dc_entries * 8
++ + nic_data->tx_dc_entries * 8);
++ max_vnics = sram_bytes / vnic_bytes;
++ for (n_vnics = 1; n_vnics < res->evq_timer_min + max_vnics;)
++ n_vnics *= 2;
++ res->rxq_max = n_vnics;
++ res->txq_max = n_vnics;
++
++ dcs = n_vnics * nic_data->tx_dc_entries * 8;
++ nic_data->tx_dc_base = sram_bytes - dcs;
++ dcs = n_vnics * nic_data->rx_dc_entries * 8;
++ nic_data->rx_dc_base = nic_data->tx_dc_base - dcs;
++ res->buffer_table_max = nic_data->rx_dc_base / 8;
++ }
++
++ if (efx->type->is_dual_func)
++ res->flags |= EFX_DL_FALCON_DUAL_FUNC;
++
++ if (EFX_INT_MODE_USE_MSI(efx))
++ res->flags |= EFX_DL_FALCON_USE_MSI;
++
++ return 0;
++}
++
++/* Probe the NIC variant (revision, ASIC vs FPGA, function count, port
++ * count, port speed). Set workaround and feature flags accordingly.
++ */
++static int falcon_probe_nic_variant(struct efx_nic *efx)
++{
++ efx_oword_t altera_build;
++
++ falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER);
++ efx->is_asic = EFX_OWORD_FIELD(altera_build, VER_ALL) == 0;
++
++#if !defined(EFX_USE_PCI_DEV_REVISION)
++ {
++ int rc;
++ rc = pci_read_config_byte(efx->pci_dev, PCI_CLASS_REVISION,
++ &efx->revision);
++ if (rc)
++ return rc;
++ }
++#endif
++ switch (FALCON_REV(efx)) {
++ case FALCON_REV_A0:
++ case 0xff:
++ EFX_ERR(efx, "Falcon rev A0 not supported\n");
++ return -ENODEV;
++
++ case FALCON_REV_A1:{
++ efx_oword_t nic_stat;
++
++ falcon_read(efx, &nic_stat, NIC_STAT_REG);
++
++ if (!efx->is_asic) {
++ EFX_ERR(efx, "Falcon rev A1 FPGA not supported\n");
++ return -ENODEV;
++ }
++ if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) {
++ EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
++ return -ENODEV;
++ }
++ efx->is_10g = EFX_OWORD_FIELD(nic_stat, STRAP_10G);
++ efx->silicon_rev = "falcon/a1";
++ break;
++ }
++
++ case FALCON_REV_B0:{
++ efx->is_10g = 1;
++ efx->silicon_rev = "falcon/b0";
++ break;
++ }
++
++ default:
++ EFX_ERR(efx, "Unknown Falcon rev %d\n", FALCON_REV(efx));
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++/* Probe all SPI devices on the NIC */
++static void falcon_probe_spi_devices(struct efx_nic *efx)
++{
++ efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
++ unsigned int has_flash, has_eeprom, boot_is_external;
++
++ falcon_read(efx, &gpio_ctl, GPIO_CTL_REG_KER);
++ falcon_read(efx, &nic_stat, NIC_STAT_REG);
++ falcon_read(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
++
++ has_flash = EFX_OWORD_FIELD(nic_stat, SF_PRST);
++ has_eeprom = EFX_OWORD_FIELD(nic_stat, EE_PRST);
++ boot_is_external = EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE);
++
++ if (has_flash) {
++ u32 flash_device_type;
++
++ if (flash_type == -1) {
++ /* Default flash SPI device: Atmel AT25F1024
++ * 128 KB, 24-bit address, 32 KB erase block,
++ * 256 B write block
++ */
++ flash_device_type =
++ (17 << SPI_DEV_TYPE_SIZE_LBN)
++ | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
++ | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
++ | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
++ | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
++ } else {
++ flash_device_type = flash_type;
++ }
++
++ falcon_spi_device_init(&efx->spi_flash, EE_SPI_FLASH,
++ flash_device_type);
++
++ if (!boot_is_external) {
++ /* Disable VPD and set clock dividers to safe
++ * values for initial programming.
++ */
++ EFX_LOG(efx, "Booted from internal ASIC settings;"
++ " setting SPI config\n");
++ EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
++ /* 125 MHz / 7 ~= 20 MHz */
++ EE_SF_CLOCK_DIV, 7,
++ /* 125 MHz / 63 ~= 2 MHz */
++ EE_EE_CLOCK_DIV, 63);
++ falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
++ }
++ }
++
++ if (has_eeprom) {
++ u32 eeprom_device_type;
++
++ /* eeprom_type may be -1 (default) for automatic detection,
++ * 0 or 1 to select the default or large EEPROM, or
++ * some larger number to specify the precise configuration
++ */
++ if (eeprom_type == -1 || eeprom_type <= 1) {
++ /* If it has no flash, it must have a large EEPROM
++ * for chip config; otherwise check whether 9-bit
++ * addressing is used for VPD configuration
++ */
++ if (eeprom_type == 0 ||
++ (eeprom_type == -1 && has_flash &&
++ (!boot_is_external ||
++ EFX_OWORD_FIELD(ee_vpd_cfg,
++ EE_VPD_EN_AD9_MODE)))) {
++ /* Default SPI device: Atmel AT25040 or similar
++ * 512 B, 9-bit address, 8 B write block
++ */
++ eeprom_device_type =
++ (9 << SPI_DEV_TYPE_SIZE_LBN)
++ | (1 << SPI_DEV_TYPE_ADDR_LEN_LBN)
++ | (3 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
++ } else {
++ /* "Large" SPI device: Atmel AT25640 or similar
++ * 8 KB, 16-bit address, 32 B write block
++ */
++ eeprom_device_type =
++ (13 << SPI_DEV_TYPE_SIZE_LBN)
++ | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
++ | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
++ }
++ } else {
++ eeprom_device_type = eeprom_type;
++ }
++
++ falcon_spi_device_init(&efx->spi_eeprom, EE_SPI_EEPROM,
++ eeprom_device_type);
++ }
++
++ EFX_LOG(efx, "flash is %s, EEPROM is %s\n",
++ (has_flash ? "present" : "absent"),
++ (has_eeprom ? "present" : "absent"));
++}
++
++static void falcon_remove_spi_devices(struct efx_nic *efx)
++{
++ kfree(efx->spi_eeprom);
++ efx->spi_eeprom = NULL;
++ kfree(efx->spi_flash);
++ efx->spi_flash = NULL;
++}
++
++#ifdef CONFIG_SFC_DEBUGFS
++
++/* Generate a hardware revision string */
++int falcon_debugfs_read_hardware_desc(struct seq_file *file, void *data)
++{
++ struct efx_nic *efx = data;
++ efx_oword_t altera_build;
++ int major, minor, build;
++ int rc, len;
++
++ if (efx->is_asic) {
++ rc = seq_puts(file, "Falcon ASIC");
++ } else {
++ falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER);
++
++ major = EFX_OWORD_FIELD(altera_build, VER_MAJOR);
++ minor = EFX_OWORD_FIELD(altera_build, VER_MINOR);
++ build = EFX_OWORD_FIELD(altera_build, VER_BUILD);
++ rc = seq_printf(file, "Falcon FPGA v%x.%x.%x",
++ major, minor, build);
++ }
++ len = rc;
++
++ switch (FALCON_REV(efx)) {
++ case FALCON_REV_A1:
++ rc = seq_puts(file, " rev A1 ");
++ break;
++ case FALCON_REV_B0:
++ rc = seq_puts(file, " rev B0 ");
++ break;
++ default:
++ rc = seq_puts(file, " rev ?? ");
++ break;
++ }
++ len += rc;
++
++ rc = seq_printf(file, "%s %s\n",
++ efx->is_10g ? "10G" : "1G", PHY_TYPE(efx));
++ len += rc;
++
++ return rc < 0 ? rc : len;
++}
++
++#endif /* CONFIG_SFC_DEBUGFS */
++
++int falcon_probe_nic(struct efx_nic *efx)
++{
++ struct falcon_nic_data *nic_data;
++ int rc;
++
++ /* Initialise I2C interface state */
++ efx->i2c.efx = efx;
++ efx->i2c.op = &falcon_i2c_bit_operations;
++ efx->i2c.sda = 1;
++ efx->i2c.scl = 1;
++
++ /* Determine number of ports etc. */
++ rc = falcon_probe_nic_variant(efx);
++ if (rc)
++ goto fail1;
++
++ /* Probe secondary function if expected */
++ if (efx->type->is_dual_func) {
++ struct pci_dev *dev = pci_dev_get(efx->pci_dev);
++
++ while ((dev = pci_get_device(EFX_VENDID_SFC, FALCON_A_S_DEVID,
++ dev))) {
++ if (dev->bus == efx->pci_dev->bus &&
++ dev->devfn == efx->pci_dev->devfn + 1) {
++ efx->pci_dev2 = dev;
++ break;
++ }
++ }
++ if (!efx->pci_dev2) {
++ EFX_ERR(efx, "failed to find secondary function\n");
++ rc = -ENODEV;
++ goto fail2;
++ }
++ }
++
++ /* Now we can reset the NIC */
++ rc = falcon_reset_hw(efx, RESET_TYPE_ALL);
++ if (rc) {
++ EFX_ERR(efx, "failed to reset NIC\n");
++ goto fail3;
++ }
++
++ /* Allocate memory for INT_KER */
++ rc = falcon_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t));
++ if (rc)
++ goto fail4;
++ BUG_ON(efx->irq_status.dma_addr & 0x0f);
++
++ EFX_LOG(efx, "INT_KER at %llx (virt %p phys %lx)\n",
++ (unsigned long long)efx->irq_status.dma_addr,
++ efx->irq_status.addr, virt_to_phys(efx->irq_status.addr));
++
++ /* Determine attached SPI devices */
++ falcon_probe_spi_devices(efx);
++
++ /* Read in the non-volatile configuration */
++ rc = falcon_probe_nvconfig(efx);
++ if (rc)
++ goto fail5;
++
++ if (!efx->is_10g && efx->phy_type != PHY_TYPE_1G_ALASKA) {
++ /* Actually using 1G port, not 10G port */
++ efx->phy_type = PHY_TYPE_1G_ALASKA;
++ efx->mii.phy_id = 2;
++ }
++
++ /* Decide how many resources we can allocate, to ourselves
++ * and to driverlink clients */
++ nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
++ efx->nic_data = (void *) nic_data;
++
++ rc = falcon_dimension_resources(efx);
++ if (rc)
++ goto fail6;
++
++ return 0;
++
++ fail6:
++ kfree(nic_data);
++ efx->nic_data = efx->dl_info = NULL;
++ fail5:
++ falcon_remove_spi_devices(efx);
++ falcon_free_buffer(efx, &efx->irq_status);
++ fail4:
++ /* fall-thru */
++ fail3:
++ if (efx->pci_dev2) {
++ pci_dev_put(efx->pci_dev2);
++ efx->pci_dev2 = NULL;
++ }
++ fail2:
++ /* fall-thru */
++ fail1:
++ return rc;
++}
++
++static int falcon_check_power_limit(struct efx_nic *efx)
++{
++ int pciecap_offset = pci_find_capability(efx->pci_dev, PCI_CAP_ID_EXP);
++ u32 pcie_devcap;
++ unsigned val, scale;
++ int rc;
++
++ if (!pciecap_offset)
++ return -EIO;
++ rc = pci_read_config_dword(efx->pci_dev,
++ (pciecap_offset + PCI_EXP_DEVCAP),
++ &pcie_devcap);
++ if (rc)
++ return rc;
++
++ val = ((pcie_devcap & PCI_EXP_DEVCAP_PWR_VAL) >>
++ PCI_EXP_DEVCAP_PWR_VAL_LBN);
++ scale = ((pcie_devcap & PCI_EXP_DEVCAP_PWR_SCL) >>
++ PCI_EXP_DEVCAP_PWR_SCL_LBN);
++
++ /* Re-scale to milliwatts if necessary */
++ while (scale != 3) {
++ val *= 10;
++ scale++;
++ }
++
++ if (val != 0 && efx->board_info.mwatts > val) {
++ EFX_ERR(efx, "board needs %d mW but only %d mW available\n",
++ efx->board_info.mwatts, val);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void falcon_init_ack_repl_timer(struct efx_nic *efx, int num_lanes)
++{
++ unsigned tlp_size;
++ efx_dword_t pcie_ack_rpl_reg;
++ efx_dword_t pcie_ack_freq_reg;
++ efx_dword_t pcie_ctrl_stat_reg;
++ u16 pcie_devicectrl;
++ int lut_index, tlp_size_decoded;
++ int current_replay, expected_replay;
++ int current_ack_timer, current_ack_freq;
++
++ static struct efx_tlp_ack_factor {
++ int tlp;
++ int replay[4]; /* 0=1x, 1=2x, 3=4x, 4=8x (see pcie docs) */
++ } tlp_ack_factor_lut[4] = {
++ { 128, { 421, 257, 174, 166 } },
++ { 256, { 689, 391, 241, 225 } },
++ { 512, { 903, 498, 295, 193 } },
++ { 1024, { 1670, 881, 487, 290 } }
++ };
++ struct efx_tlp_ack_factor *tlp_ack_factor;
++
++ /* Get TLP size */
++ falcon_pcie_core_read_reg(efx, PCIE_CORE_ADDR_PCIE_DEVICE_CTRL_STAT,
++ &pcie_ctrl_stat_reg);
++ pcie_devicectrl = (u16) EFX_EXTRACT_DWORD(pcie_ctrl_stat_reg, 0, 15);
++ tlp_size = ((PCI_EXP_DEVCTL_PAYLOAD & pcie_devicectrl) >>
++ ffs(PCI_EXP_DEVCTL_PAYLOAD));
++ EFX_WARN_ON_PARANOID(tlp_size > 3); /* => 1024 bytes */
++ tlp_ack_factor = &tlp_ack_factor_lut[tlp_size & 0x3];
++ tlp_size_decoded = tlp_ack_factor->tlp;
++
++ /* Get actual ack & actual and expected replay settings */
++ falcon_pcie_core_read_reg(efx, PCIE_CORE_ADDR_ACK_RPL_TIMER,
++ &pcie_ack_rpl_reg);
++ current_replay = EFX_DWORD_FIELD(pcie_ack_rpl_reg, PCIE_CORE_RPL_TL);
++ current_ack_timer = EFX_DWORD_FIELD(pcie_ack_rpl_reg,
++ PCIE_CORE_ACK_TL);
++
++ lut_index = ffs(num_lanes) - 1;
++ expected_replay = tlp_ack_factor->replay[lut_index & 0x3];
++
++ falcon_pcie_core_read_reg(efx, PCIE_CORE_ADDR_ACK_FREQ,
++ &pcie_ack_freq_reg);
++ current_ack_freq = EFX_DWORD_FIELD(pcie_ack_freq_reg,
++ PCIE_CORE_ACK_FREQ);
++
++ EFX_LOG(efx, "pcie x%d tlp=%d replay_reg=" EFX_DWORD_FMT " { ack=%d "
++ "current_replay=%d expected_replay=%d } ack_reg="
++ EFX_DWORD_FMT " { current_freq=%d expected_freq=%d }\n",
++ num_lanes, tlp_size_decoded,
++ EFX_DWORD_VAL(pcie_ack_rpl_reg), current_ack_timer,
++ current_replay, expected_replay,
++ EFX_DWORD_VAL(pcie_ack_rpl_reg), current_ack_freq, 0);
++
++ /* If expected replay setting needs to be bigger then set it */
++ if (expected_replay > current_replay) {
++ EFX_SET_DWORD_FIELD(pcie_ack_rpl_reg, PCIE_CORE_RPL_TL,
++ expected_replay);
++
++ falcon_pcie_core_write_reg(efx, PCIE_CORE_ADDR_ACK_RPL_TIMER,
++ pcie_ack_rpl_reg);
++ }
++}
++
++static int falcon_init_pcie_core(struct efx_nic *efx)
++{
++ int pciecap_offset;
++ unsigned num_lanes = 0;
++
++ /* Get num lanes */
++ pciecap_offset = pci_find_capability(efx->pci_dev, PCI_CAP_ID_EXP);
++ if (pciecap_offset) {
++ u16 pcie_linkstat;
++ int rc, link_sta;
++
++ link_sta = pciecap_offset + PCI_EXP_LNKSTA;
++ rc = pci_read_config_word(efx->pci_dev, link_sta,
++ &pcie_linkstat);
++ if (rc)
++ return rc;
++
++ num_lanes = ((pcie_linkstat & PCI_EXP_LNKSTA_LNK_WID)
++ >> PCI_EXP_LNKSTA_LNK_WID_LBN);
++ EFX_BUG_ON_PARANOID(num_lanes <= 0 || num_lanes > 8);
++
++ if (num_lanes < 8)
++ EFX_ERR(efx, "WARNING: the Solarflare Network Adapter "
++ "has been plugged into a PCI-Express slot with "
++ "less than 8 lanes (%d detected). This will "
++ "limit the maximum achievable bandwidth! "
++ "Consult your motherboard documentation to "
++ "find a slot that is 8 lanes electrically and "
++ "physically\n", num_lanes);
++ }
++
++ if (FALCON_REV(efx) <= FALCON_REV_A1)
++ return 0;
++
++ if (EFX_WORKAROUND_6943(efx) && num_lanes > 0)
++ falcon_init_ack_repl_timer(efx, num_lanes);
++
++ if (EFX_WORKAROUND_9096(efx)) {
++ efx_dword_t pcie_ack_freq_reg;
++
++ /* ensure ack freq timer is 0 = always ack after timeout */
++ falcon_pcie_core_read_reg(efx, PCIE_CORE_ADDR_ACK_FREQ,
++ &pcie_ack_freq_reg);
++ EFX_SET_DWORD_FIELD(pcie_ack_freq_reg, PCIE_CORE_ACK_FREQ, 0);
++ falcon_pcie_core_write_reg(efx, PCIE_CORE_ADDR_ACK_FREQ,
++ pcie_ack_freq_reg);
++ }
++
++ return 0;
++}
++
++static void falcon_fini_pcie_core(struct efx_nic *efx)
++{
++ efx_dword_t pcie_ack_freq_reg;
++
++ if (FALCON_REV(efx) <= FALCON_REV_A1)
++ return;
++
++ if (EFX_WORKAROUND_9096(efx)) {
++ /* Set the ACK frequency timer to 1, so TLP's are acked in
++ * a timely fashion.
++ */
++ falcon_pcie_core_read_reg(efx, PCIE_CORE_ADDR_ACK_FREQ,
++ &pcie_ack_freq_reg);
++ EFX_SET_DWORD_FIELD(pcie_ack_freq_reg, PCIE_CORE_ACK_FREQ, 1);
++ falcon_pcie_core_write_reg(efx, PCIE_CORE_ADDR_ACK_FREQ,
++ pcie_ack_freq_reg);
++ }
++}
++
++/* This call performs hardware-specific global initialisation, such as
++ * defining the descriptor cache sizes and number of RSS channels.
++ * It does not set up any buffers, descriptor rings or event queues.
++ */
++int falcon_init_nic(struct efx_nic *efx)
++{
++ struct falcon_nic_data *data;
++ efx_oword_t temp;
++ unsigned thresh;
++ int rc;
++
++ data = (struct falcon_nic_data *)efx->nic_data;
++
++ /* Set up the address region register. This is only needed
++ * for the B0 FPGA, but since we are just pushing in the
++ * reset defaults this may as well be unconditional. */
++ EFX_POPULATE_OWORD_4(temp, ADR_REGION0, 0,
++ ADR_REGION1, (1 << 16),
++ ADR_REGION2, (2 << 16),
++ ADR_REGION3, (3 << 16));
++ falcon_write(efx, &temp, ADR_REGION_REG_KER);
++
++ /* Use on-chip SRAM if needed.
++ */
++ falcon_read(efx, &temp, NIC_STAT_REG);
++ if (efx->external_sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY)
++ EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
++ else
++ EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 0);
++ falcon_write(efx, &temp, NIC_STAT_REG);
++
++ /* Check power requirements against PCIe power budgeting */
++ rc = falcon_check_power_limit(efx);
++ if (rc)
++ return rc;
++
++ /* Warn if <8 lanes of PCIe detected & set pcie timers */
++ rc = falcon_init_pcie_core(efx);
++ if (rc)
++ return rc;
++
++ /* Set buffer table mode */
++ EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL);
++ falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER);
++
++ rc = falcon_reset_sram(efx);
++ if (rc)
++ return rc;
++
++ /* Set positions of descriptor caches in SRAM. */
++ EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, data->tx_dc_base / 8);
++ falcon_write(efx, &temp, SRM_TX_DC_CFG_REG_KER);
++ EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, data->rx_dc_base / 8);
++ falcon_write(efx, &temp, SRM_RX_DC_CFG_REG_KER);
++
++ /* Set TX descriptor cache size. */
++ EFX_POPULATE_OWORD_1(temp, TX_DC_SIZE, ffs(data->tx_dc_entries) - 4);
++ falcon_write(efx, &temp, TX_DC_CFG_REG_KER);
++
++ /* Set RX descriptor cache size. Set low watermark to size-8, as
++ * this allows most efficient prefetching.
++ */
++ EFX_POPULATE_OWORD_1(temp, RX_DC_SIZE, ffs(data->rx_dc_entries) - 4);
++ falcon_write(efx, &temp, RX_DC_CFG_REG_KER);
++ EFX_POPULATE_OWORD_1(temp, RX_DC_PF_LWM, data->rx_dc_entries - 8);
++ falcon_write(efx, &temp, RX_DC_PF_WM_REG_KER);
++
++ /* Clear the parity enables on the TX data fifos as
++ * they produce false parity errors because of timing issues
++ */
++ if (EFX_WORKAROUND_5129(efx)) {
++ falcon_read(efx, &temp, SPARE_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, MEM_PERR_EN_TX_DATA, 0);
++ falcon_write(efx, &temp, SPARE_REG_KER);
++ }
++
++ /* Enable all the genuinely fatal interrupts. (They are still
++ * masked by the overall interrupt mask, controlled by
++ * falcon_interrupts()).
++ *
++ * Note: All other fatal interrupts are enabled
++ */
++ EFX_POPULATE_OWORD_3(temp,
++ ILL_ADR_INT_KER_EN, 1,
++ RBUF_OWN_INT_KER_EN, 1,
++ TBUF_OWN_INT_KER_EN, 1);
++ EFX_INVERT_OWORD(temp);
++ falcon_write(efx, &temp, FATAL_INTR_REG_KER);
++
++ /* Set number of RSS queues for receive path. */
++ falcon_read(efx, &temp, RX_FILTER_CTL_REG);
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ EFX_SET_OWORD_FIELD(temp, NUM_KER, 0);
++ else
++ EFX_SET_OWORD_FIELD(temp, NUM_KER, efx->rss_queues - 1);
++ if (EFX_WORKAROUND_7244(efx)) {
++ EFX_SET_OWORD_FIELD(temp, UDP_FULL_SRCH_LIMIT, 8);
++ EFX_SET_OWORD_FIELD(temp, UDP_WILD_SRCH_LIMIT, 8);
++ EFX_SET_OWORD_FIELD(temp, TCP_FULL_SRCH_LIMIT, 8);
++ EFX_SET_OWORD_FIELD(temp, TCP_WILD_SRCH_LIMIT, 8);
++ }
++ falcon_write(efx, &temp, RX_FILTER_CTL_REG);
++
++ falcon_setup_rss_indir_table(efx);
++
++ /* Setup RX. Wait for descriptor is broken and must
++ * be disabled. RXDP recovery shouldn't be needed, but is.
++ */
++ falcon_read(efx, &temp, RX_SELF_RST_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, RX_NODESC_WAIT_DIS, 1);
++ EFX_SET_OWORD_FIELD(temp, RX_RECOVERY_EN, 1);
++ if (EFX_WORKAROUND_5583(efx))
++ EFX_SET_OWORD_FIELD(temp, RX_ISCSI_DIS, 1);
++ falcon_write(efx, &temp, RX_SELF_RST_REG_KER);
++
++ /* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be
++ * controlled by the RX FIFO fill level. Set arbitration to one pkt/Q.
++ */
++ falcon_read(efx, &temp, TX_CFG2_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, TX_RX_SPACER, 0xfe);
++ EFX_SET_OWORD_FIELD(temp, TX_RX_SPACER_EN, 1);
++ EFX_SET_OWORD_FIELD(temp, TX_ONE_PKT_PER_Q, 1);
++ EFX_SET_OWORD_FIELD(temp, TX_CSR_PUSH_EN, 0);
++ EFX_SET_OWORD_FIELD(temp, TX_DIS_NON_IP_EV, 1);
++ /* Enable SW_EV to inherit in char driver - assume harmless here */
++ EFX_SET_OWORD_FIELD(temp, TX_SW_EV_EN, 1);
++ /* Prefetch threshold 2 => fetch when descriptor cache half empty */
++ EFX_SET_OWORD_FIELD(temp, TX_PREF_THRESHOLD, 2);
++ if (EFX_WORKAROUND_9008(efx))
++ EFX_SET_OWORD_FIELD(temp, TX_PREF_WD_TMR, (unsigned)0x3fffff);
++ /* Squash TX of packets of 16 bytes or less */
++ if (FALCON_REV(efx) >= FALCON_REV_B0 && EFX_WORKAROUND_9141(efx))
++ EFX_SET_OWORD_FIELD(temp, TX_FLUSH_MIN_LEN_EN_B0, 1);
++ falcon_write(efx, &temp, TX_CFG2_REG_KER);
++
++ /* Do not enable TX_NO_EOP_DISC_EN, since it limits packets to 16
++ * descriptors (which is bad).
++ */
++ falcon_read(efx, &temp, TX_CFG_REG_KER);
++ EFX_SET_OWORD_FIELD(temp, TX_NO_EOP_DISC_EN, 0);
++ falcon_write(efx, &temp, TX_CFG_REG_KER);
++
++ /* RX config */
++ falcon_read(efx, &temp, RX_CFG_REG_KER);
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_DESC_PUSH_EN, 0);
++ if (EFX_WORKAROUND_7575(efx))
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_USR_BUF_SIZE,
++ (3 * 4096) / 32);
++ if (FALCON_REV(efx) >= FALCON_REV_B0)
++ EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 1);
++
++ /* RX FIFO flow control thresholds */
++ thresh = ((rx_xon_thresh_bytes >= 0) ?
++ rx_xon_thresh_bytes : efx->type->rx_xon_thresh);
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XON_MAC_TH, thresh / 256);
++ thresh = ((rx_xoff_thresh_bytes >= 0) ?
++ rx_xoff_thresh_bytes : efx->type->rx_xoff_thresh);
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_MAC_TH, thresh / 256);
++ /* RX control FIFO thresholds [32 entries] */
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XON_TX_TH, 25);
++ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_TX_TH, 20);
++ falcon_write(efx, &temp, RX_CFG_REG_KER);
++
++ /* Set destination of both TX and RX Flush events */
++ if (FALCON_REV(efx) >= FALCON_REV_B0) {
++ EFX_POPULATE_OWORD_1(temp, FLS_EVQ_ID, 0);
++ falcon_write(efx, &temp, DP_CTRL_REG);
++ }
++
++ return 0;
++}
++
++void falcon_fini_nic(struct efx_nic *efx)
++{
++ falcon_fini_pcie_core(efx);
++}
++
++void falcon_remove_nic(struct efx_nic *efx)
++{
++ /* Tear down the private nic state, and the driverlink nic params */
++ kfree(efx->nic_data);
++ efx->nic_data = efx->dl_info = NULL;
++
++ falcon_remove_spi_devices(efx);
++ falcon_free_buffer(efx, &efx->irq_status);
++
++ /* Reset the NIC finally */
++ (void) falcon_reset_hw(efx, RESET_TYPE_ALL);
++
++ /* Release the second function after the reset */
++ if (efx->pci_dev2) {
++ pci_dev_put(efx->pci_dev2);
++ efx->pci_dev2 = NULL;
++ }
++}
++
++void falcon_update_nic_stats(struct efx_nic *efx)
++{
++ efx_oword_t cnt;
++
++ /* Read the RX drop counter */
++ falcon_read(efx, &cnt, RX_NODESC_DROP_REG_KER);
++ efx->n_rx_nodesc_drop_cnt += EFX_OWORD_FIELD(cnt, RX_NODESC_DROP_CNT);
++}
++
++/**************************************************************************
++ *
++ * Revision-dependent attributes used by efx.c
++ *
++ **************************************************************************
++ */
++
++struct efx_nic_type falcon_a_nic_type = {
++ .is_dual_func = 1,
++ .mem_bar = 2,
++ .mem_map_size = 0x20000,
++ .txd_ptr_tbl_base = TX_DESC_PTR_TBL_KER_A1,
++ .rxd_ptr_tbl_base = RX_DESC_PTR_TBL_KER_A1,
++ .buf_tbl_base = BUF_TBL_KER_A1,
++ .evq_ptr_tbl_base = EVQ_PTR_TBL_KER_A1,
++ .evq_rptr_tbl_base = EVQ_RPTR_REG_KER_A1,
++ .txd_ring_mask = FALCON_TXD_RING_MASK,
++ .rxd_ring_mask = FALCON_RXD_RING_MASK,
++ .evq_size = FALCON_EVQ_SIZE,
++ .max_dma_mask = FALCON_DMA_MASK,
++ .tx_dma_mask = FALCON_TX_DMA_MASK,
++ .bug5391_mask = 0xf,
++ .rx_xoff_thresh = 2048,
++ .rx_xon_thresh = 512,
++ .rx_buffer_padding = 0x24,
++ .max_interrupt_mode = EFX_INT_MODE_MSI,
++ .phys_addr_channels = 4,
++};
++
++struct efx_nic_type falcon_b_nic_type = {
++ .is_dual_func = 0,
++ .mem_bar = 2,
++ /* Map everything up to and including the RSS indirection
++ * table. Don't map MSI-X table, MSI-X PBA since Linux
++ * requires that they not be mapped. */
++ .mem_map_size = RX_RSS_INDIR_TBL_B0 + 0x800,
++ .txd_ptr_tbl_base = TX_DESC_PTR_TBL_KER_B0,
++ .rxd_ptr_tbl_base = RX_DESC_PTR_TBL_KER_B0,
++ .buf_tbl_base = BUF_TBL_KER_B0,
++ .evq_ptr_tbl_base = EVQ_PTR_TBL_KER_B0,
++ .evq_rptr_tbl_base = EVQ_RPTR_REG_KER_B0,
++ .txd_ring_mask = FALCON_TXD_RING_MASK,
++ .rxd_ring_mask = FALCON_RXD_RING_MASK,
++ .evq_size = FALCON_EVQ_SIZE,
++ .max_dma_mask = FALCON_DMA_MASK,
++ .tx_dma_mask = FALCON_TX_DMA_MASK,
++ .bug5391_mask = 0,
++ .rx_xoff_thresh = 54272, /* ~80Kb - 3*max MTU */
++ .rx_xon_thresh = 27648, /* ~3*max MTU */
++ .rx_buffer_padding = 0,
++ .max_interrupt_mode = EFX_INT_MODE_MSIX,
++ .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy
++ * interrupt handler only supports 32
++ * channels */
++
++};
++
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/falcon_gmac.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon_gmac.c
+--- linux-2.6.18.8/drivers/net/sfc/falcon_gmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon_gmac.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,320 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/delay.h>
++#include "net_driver.h"
++#include "efx.h"
++#include "falcon.h"
++#include "mac.h"
++#include "falcon_hwdefs.h"
++#include "falcon_io.h"
++#include "gmii.h"
++
++/**************************************************************************
++ *
++ * MAC register access
++ *
++ **************************************************************************/
++
++/* Offset of a GMAC register within Falcon */
++#define FALCON_GMAC_REG(mac_reg) \
++ (FALCON_GMAC_REGBANK + ((mac_reg) * FALCON_GMAC_REG_SIZE))
++
++static void falcon_gmac_writel(struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg)
++{
++ efx_oword_t temp;
++
++ EFX_POPULATE_OWORD_1(temp, MAC_DATA, EFX_DWORD_FIELD(*value, MAC_DATA));
++ falcon_write(efx, &temp, FALCON_GMAC_REG(mac_reg));
++}
++
++static void falcon_gmac_readl(struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg)
++{
++ efx_oword_t temp;
++
++ falcon_read(efx, &temp, FALCON_GMAC_REG(mac_reg));
++ EFX_POPULATE_DWORD_1(*value, MAC_DATA, EFX_OWORD_FIELD(temp, MAC_DATA));
++}
++
++/**************************************************************************
++ *
++ * MAC operations
++ *
++ *************************************************************************/
++
++static int falcon_init_gmac(struct efx_nic *efx)
++{
++ int rc;
++
++ /* Reset the MAC */
++ mentormac_reset(efx);
++
++ /* Initialise PHY */
++ rc = efx->phy_op->init(efx);
++ if (rc)
++ return rc;
++
++ return 0;
++}
++
++static void falcon_reconfigure_gmac(struct efx_nic *efx)
++{
++ /* Reconfigure PHY and pick up PHY parameters. This updates
++ * the link status. */
++ efx->phy_op->reconfigure(efx);
++
++ /* Isolate the MAC. */
++ falcon_deconfigure_mac_wrapper(efx);
++
++ /* Reconfigure MAC */
++ mentormac_reconfigure(efx);
++
++ /* Reconfigure MAC wrapper */
++ falcon_reconfigure_mac_wrapper(efx);
++}
++
++static void falcon_fini_gmac(struct efx_nic *efx)
++{
++ /* Isolate the MAC - PHY */
++ falcon_deconfigure_mac_wrapper(efx);
++
++ /* Shut down PHY */
++ efx->phy_op->fini(efx);
++
++ /* Reset MAC */
++ mentormac_reset(efx);
++}
++
++static void falcon_update_stats_gmac(struct efx_nic *efx)
++{
++ struct efx_mac_stats *mac_stats = &efx->mac_stats;
++ unsigned long old_rx_pause, old_tx_pause;
++ unsigned long new_rx_pause, new_tx_pause;
++ int rc;
++
++ rc = falcon_dma_stats(efx, GDmaDone_offset);
++ if (rc)
++ return;
++
++ /* Pause frames are erroneously counted as errors (SFC bug 3269) */
++ old_rx_pause = mac_stats->rx_pause;
++ old_tx_pause = mac_stats->tx_pause;
++
++ /* Update MAC stats from DMAed values */
++ FALCON_STAT(efx, GRxGoodOct, rx_good_bytes);
++ FALCON_STAT(efx, GRxBadOct, rx_bad_bytes);
++ FALCON_STAT(efx, GRxMissPkt, rx_missed);
++ FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier);
++ FALCON_STAT(efx, GRxPausePkt, rx_pause);
++ FALCON_STAT(efx, GRxBadPkt, rx_bad);
++ FALCON_STAT(efx, GRxUcastPkt, rx_unicast);
++ FALCON_STAT(efx, GRxMcastPkt, rx_multicast);
++ FALCON_STAT(efx, GRxBcastPkt, rx_broadcast);
++ FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64);
++ FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64);
++ FALCON_STAT(efx, GRx64Pkt, rx_64);
++ FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127);
++ FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255);
++ FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511);
++ FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023);
++ FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx);
++ FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo);
++ FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo);
++ FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx);
++ FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo);
++ FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo);
++ FALCON_STAT(efx, GTxGoodBadOct, tx_bytes);
++ FALCON_STAT(efx, GTxGoodOct, tx_good_bytes);
++ FALCON_STAT(efx, GTxSglColPkt, tx_single_collision);
++ FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision);
++ FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision);
++ FALCON_STAT(efx, GTxDefPkt, tx_deferred);
++ FALCON_STAT(efx, GTxLateCol, tx_late_collision);
++ FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred);
++ FALCON_STAT(efx, GTxPausePkt, tx_pause);
++ FALCON_STAT(efx, GTxBadPkt, tx_bad);
++ FALCON_STAT(efx, GTxUcastPkt, tx_unicast);
++ FALCON_STAT(efx, GTxMcastPkt, tx_multicast);
++ FALCON_STAT(efx, GTxBcastPkt, tx_broadcast);
++ FALCON_STAT(efx, GTxLt64Pkt, tx_lt64);
++ FALCON_STAT(efx, GTx64Pkt, tx_64);
++ FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127);
++ FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255);
++ FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511);
++ FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023);
++ FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx);
++ FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo);
++ FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo);
++ FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp);
++ FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error);
++ FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error);
++
++ /* Pause frames are erroneously counted as errors (SFC bug 3269) */
++ new_rx_pause = mac_stats->rx_pause;
++ new_tx_pause = mac_stats->tx_pause;
++ mac_stats->rx_bad -= (new_rx_pause - old_rx_pause);
++ mac_stats->tx_bad -= (new_tx_pause - old_tx_pause);
++
++ /* Derive stats that the MAC doesn't provide directly */
++ mac_stats->tx_bad_bytes =
++ mac_stats->tx_bytes - mac_stats->tx_good_bytes;
++ mac_stats->tx_packets =
++ mac_stats->tx_lt64 + mac_stats->tx_64 +
++ mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 +
++ mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 +
++ mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo +
++ mac_stats->tx_gtjumbo;
++ mac_stats->tx_collision =
++ mac_stats->tx_single_collision +
++ mac_stats->tx_multiple_collision +
++ mac_stats->tx_excessive_collision +
++ mac_stats->tx_late_collision;
++ mac_stats->rx_bytes =
++ mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes;
++ mac_stats->rx_packets =
++ mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 +
++ mac_stats->rx_64 + mac_stats->rx_65_to_127 +
++ mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 +
++ mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx +
++ mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo;
++ mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad;
++ mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
++}
++
++static int falcon_check_gmac(struct efx_nic *efx)
++{
++ /* Nothing to do */
++ return 0;
++}
++
++static void falcon_gmac_sim_phy_event(struct efx_nic *efx)
++{
++ efx_qword_t phy_event;
++
++ EFX_POPULATE_QWORD_2(phy_event,
++ EV_CODE, GLOBAL_EV_DECODE,
++ G_PHY0_INTR, 1);
++ falcon_generate_event(&efx->channel[0], &phy_event);
++}
++
++static void falcon_gmac_reset_phy(struct efx_nic *efx)
++{
++ struct mii_if_info *gmii = &efx->mii;
++ int bmcr, i;
++
++ /* Perform software reset to make new settings take effect */
++ bmcr = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_BMCR);
++ bmcr |= BMCR_RESET;
++ gmii->mdio_write(gmii->dev, gmii->phy_id, MII_BMCR, bmcr);
++
++ /* Wait for the reset to deassert */
++ for (i = 20; i; --i) {
++ udelay(10);
++ if ((gmii->mdio_read(gmii->dev, gmii->phy_id, MII_BMCR) &
++ BMCR_RESET) == 0)
++ return;
++ }
++
++ EFX_ERR(efx, "wait for PHY reset timed out\n");
++}
++
++
++static int falcon_gmac_get_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd)
++{
++ struct mii_if_info *gmii = &efx->mii;
++ int rc;
++
++ rc = mii_ethtool_gset(gmii, ecmd);
++ ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
++ return rc;
++}
++
++static int falcon_gmac_set_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd)
++{
++ struct mii_if_info *gmii = &efx->mii;
++ int rc;
++
++ /* 1000Mbps half-duplex is technically legal, but none of our
++ * current hardware supports it, so just disallow it. */
++ if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) {
++ EFX_LOG(efx, "rejecting unsupported 1000Mbps HD"
++ " setting\n");
++ return -EINVAL;
++ }
++
++ /* Use MII to set all other settings */
++ rc = mii_ethtool_sset(gmii, ecmd);
++ if (rc)
++ return rc;
++
++ /* Reset the PHY */
++ falcon_gmac_reset_phy(efx);
++
++ return 0;
++}
++
++static int falcon_gmac_set_pause(struct efx_nic *efx,
++ enum efx_fc_type flow_control)
++{
++ struct mii_if_info *gmii = &efx->mii;
++ int adv;
++
++ /* GMAC has tiny MAC FIFO, so TX flow control won't work */
++ if (flow_control & EFX_FC_TX)
++ return -EINVAL;
++
++ efx->flow_control = flow_control;
++
++ /* Push autonegotiation to PHY */
++ adv = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_ADVERTISE);
++ adv &= ~GM_ADVERTISE_PAUSE_CAP;
++ adv |= (flow_control & EFX_FC_AUTO) ? GM_ADVERTISE_PAUSE_CAP : 0;
++ gmii->mdio_write(gmii->dev, gmii->phy_id, MII_ADVERTISE, adv);
++
++ falcon_gmac_reset_phy(efx);
++
++ return 0;
++}
++
++
++struct efx_mac_operations falcon_gmac_operations = {
++ .mac_writel = falcon_gmac_writel,
++ .mac_readl = falcon_gmac_readl,
++ .init = falcon_init_gmac,
++ .reconfigure = falcon_reconfigure_gmac,
++ .update_stats = falcon_update_stats_gmac,
++ .fini = falcon_fini_gmac,
++ .check_hw = falcon_check_gmac,
++ .fake_phy_event = falcon_gmac_sim_phy_event,
++ .get_settings = falcon_gmac_get_settings,
++ .set_settings = falcon_gmac_set_settings,
++ .set_pause = falcon_gmac_set_pause,
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/falcon.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon.h
+--- linux-2.6.18.8/drivers/net/sfc/falcon.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,177 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_FALCON_H
++#define EFX_FALCON_H
++
++#include <asm/io.h>
++#include <linux/spinlock.h>
++#include "net_driver.h"
++
++/*
++ * Falcon hardware control
++ */
++
++enum falcon_revision {
++ FALCON_REV_A0 = 0,
++ FALCON_REV_A1 = 1,
++ FALCON_REV_B0 = 2,
++};
++
++#if defined(EFX_USE_PCI_DEV_REVISION)
++#define FALCON_REV(efx) ((efx)->pci_dev->revision)
++#else
++#define FALCON_REV(efx) ((efx)->revision)
++#endif
++
++extern struct efx_nic_type falcon_a_nic_type;
++extern struct efx_nic_type falcon_b_nic_type;
++
++/**************************************************************************
++ *
++ * Externs
++ *
++ **************************************************************************
++ */
++
++/* TX data path */
++extern int falcon_probe_tx(struct efx_tx_queue *tx_queue);
++extern int falcon_init_tx(struct efx_tx_queue *tx_queue);
++extern void falcon_fini_tx(struct efx_tx_queue *tx_queue);
++extern void falcon_remove_tx(struct efx_tx_queue *tx_queue);
++#if defined(EFX_USE_FASTCALL)
++extern void fastcall falcon_push_buffers(struct efx_tx_queue *tx_queue);
++#else
++extern void falcon_push_buffers(struct efx_tx_queue *tx_queue);
++#endif
++
++/* RX data path */
++extern int falcon_probe_rx(struct efx_rx_queue *rx_queue);
++extern int falcon_init_rx(struct efx_rx_queue *rx_queue);
++extern void falcon_fini_rx(struct efx_rx_queue *rx_queue);
++extern void falcon_remove_rx(struct efx_rx_queue *rx_queue);
++#if defined(EFX_USE_FASTCALL)
++extern void fastcall falcon_notify_rx_desc(struct efx_rx_queue *rx_queue);
++#else
++extern void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue);
++#endif
++
++/* Event data path */
++extern int falcon_probe_eventq(struct efx_channel *channel);
++extern int falcon_init_eventq(struct efx_channel *channel);
++extern void falcon_fini_eventq(struct efx_channel *channel);
++extern void falcon_remove_eventq(struct efx_channel *channel);
++#if defined(EFX_USE_FASTCALL)
++extern int fastcall falcon_process_eventq(struct efx_channel *channel,
++ int *rx_quota);
++#else
++extern int falcon_process_eventq(struct efx_channel *channel, int *rx_quota);
++#endif
++#if defined(EFX_USE_FASTCALL)
++extern void fastcall falcon_eventq_read_ack(struct efx_channel *channel);
++#else
++extern void falcon_eventq_read_ack(struct efx_channel *channel);
++#endif
++
++/* Ports */
++extern int falcon_probe_port(struct efx_nic *efx);
++extern void falcon_remove_port(struct efx_nic *efx);
++
++/* MAC/PHY */
++extern void falcon_check_xaui_link_up(struct efx_nic *efx);
++extern int falcon_xaui_link_ok(struct efx_nic *efx);
++extern int falcon_dma_stats(struct efx_nic *efx,
++ unsigned int done_offset);
++extern void falcon_drain_tx_fifo(struct efx_nic *efx);
++extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx);
++extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
++
++/* Interrupts and test events */
++extern int falcon_init_interrupt(struct efx_nic *efx);
++extern void falcon_enable_interrupts(struct efx_nic *efx);
++extern void falcon_generate_test_event(struct efx_channel *channel,
++ unsigned int magic);
++extern void falcon_generate_interrupt(struct efx_nic *efx);
++extern void falcon_set_int_moderation(struct efx_channel *channel);
++extern void falcon_disable_interrupts(struct efx_nic *efx);
++extern void falcon_fini_interrupt(struct efx_nic *efx);
++
++/* Global Resources */
++extern int falcon_probe_nic(struct efx_nic *efx);
++extern int falcon_probe_resources(struct efx_nic *efx);
++extern int falcon_init_nic(struct efx_nic *efx);
++extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method);
++extern void falcon_fini_nic(struct efx_nic *efx);
++extern void falcon_remove_resources(struct efx_nic *efx);
++extern void falcon_remove_nic(struct efx_nic *efx);
++extern void falcon_update_nic_stats(struct efx_nic *efx);
++extern void falcon_set_multicast_hash(struct efx_nic *efx);
++extern int falcon_reset_xaui(struct efx_nic *efx);
++
++/**************************************************************************
++ *
++ * Falcon MAC stats
++ *
++ **************************************************************************
++ */
++
++#define FALCON_STAT_OFFSET(falcon_stat) EFX_VAL(falcon_stat, offset)
++#define FALCON_STAT_WIDTH(falcon_stat) EFX_VAL(falcon_stat, WIDTH)
++
++/* Retrieve statistic from statistics block */
++#define FALCON_STAT(efx, falcon_stat, efx_stat) do { \
++ if (FALCON_STAT_WIDTH(falcon_stat) == 16) \
++ (efx)->mac_stats.efx_stat += le16_to_cpu( \
++ *((__force __le16 *) \
++ (efx->stats_buffer.addr + \
++ FALCON_STAT_OFFSET(falcon_stat)))); \
++ else if (FALCON_STAT_WIDTH(falcon_stat) == 32) \
++ (efx)->mac_stats.efx_stat += le32_to_cpu( \
++ *((__force __le32 *) \
++ (efx->stats_buffer.addr + \
++ FALCON_STAT_OFFSET(falcon_stat)))); \
++ else \
++ (efx)->mac_stats.efx_stat += le64_to_cpu( \
++ *((__force __le64 *) \
++ (efx->stats_buffer.addr + \
++ FALCON_STAT_OFFSET(falcon_stat)))); \
++ } while (0)
++
++#define FALCON_MAC_STATS_SIZE 0x100
++
++#define MAC_DATA_LBN 0
++#define MAC_DATA_WIDTH 32
++
++extern void falcon_generate_event(struct efx_channel *channel,
++ efx_qword_t *event);
++
++#ifdef CONFIG_SFC_DEBUGFS
++struct seq_file;
++extern int falcon_debugfs_read_hardware_desc(struct seq_file *file, void *data);
++#endif
++
++#endif /* EFX_FALCON_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/falcon_hwdefs.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon_hwdefs.h
+--- linux-2.6.18.8/drivers/net/sfc/falcon_hwdefs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon_hwdefs.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1620 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_FALCON_HWDEFS_H
++#define EFX_FALCON_HWDEFS_H
++
++/*
++ * Falcon hardware value definitions.
++ * Falcon is the internal codename for the SFC4000 controller that is
++ * present in SFE400X evaluation boards
++ */
++
++/**************************************************************************
++ *
++ * Falcon registers
++ *
++ **************************************************************************
++ */
++
++/* Address region register */
++#define ADR_REGION_REG_KER 0x00
++#define ADR_REGION0_LBN 0
++#define ADR_REGION0_WIDTH 18
++#define ADR_REGION1_LBN 32
++#define ADR_REGION1_WIDTH 18
++#define ADR_REGION2_LBN 64
++#define ADR_REGION2_WIDTH 18
++#define ADR_REGION3_LBN 96
++#define ADR_REGION3_WIDTH 18
++
++/* Interrupt enable register */
++#define INT_EN_REG_KER 0x0010
++#define INT_LEVEL_SEL_LBN 8
++#define INT_LEVEL_SEL_WIDTH 6
++#define MEM_PERR_INT_EN_KER_LBN 5
++#define MEM_PERR_INT_EN_KER_WIDTH 1
++#define KER_INT_CHAR_LBN 4
++#define KER_INT_CHAR_WIDTH 1
++#define KER_INT_KER_LBN 3
++#define KER_INT_KER_WIDTH 1
++#define ILL_ADR_ERR_INT_EN_KER_LBN 2
++#define ILL_ADR_ERR_INT_EN_KER_WIDTH 1
++#define SRM_PERR_INT_EN_KER_LBN 1
++#define SRM_PERR_INT_EN_KER_WIDTH 1
++#define DRV_INT_EN_KER_LBN 0
++#define DRV_INT_EN_KER_WIDTH 1
++
++/* Interrupt status address register */
++#define INT_ADR_REG_KER 0x0030
++#define NORM_INT_VEC_DIS_KER_LBN 64
++#define NORM_INT_VEC_DIS_KER_WIDTH 1
++#define INT_ADR_KER_LBN 0
++#define INT_ADR_KER_WIDTH EFX_DMA_TYPE_WIDTH(64) /* not 46 for this one */
++
++/* Interrupt status register (B0 only) */
++#define INT_ISR0_B0 0x90
++#define INT_ISR1_B0 0xA0
++
++/* Interrupt acknowledge register (A0/A1 only) */
++#define INT_ACK_REG_KER_A1 0x0050
++#define INT_ACK_DUMMY_DATA_LBN 0
++#define INT_ACK_DUMMY_DATA_WIDTH 32
++
++/* Interrupt acknowledge work-around register (A0/A1 only )*/
++#define WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 0x0070
++
++/* Hardware initialisation register */
++#define HW_INIT_REG_KER 0x00c0
++#define BCSR_TARGET_MASK_LBN 101
++#define BCSR_TARGET_MASK_WIDTH 4
++#define PCIE_TIMEOUT_DIS_LBN 123
++#define PCIE_TIMEOUT_DIS_WIDTH 1
++#define B2B_REQ_EN_B0_LBN 45
++#define B2B_REQ_EN_B0_WIDTH 1
++#define FC_BLOCKING_EN_B0_LBN 44
++#define FC_BLOCKING_EN_B0_WIDTH 1
++
++/* SPI host command register */
++#define EE_SPI_HCMD_REG_KER 0x0100
++#define EE_SPI_HCMD_CMD_EN_LBN 31
++#define EE_SPI_HCMD_CMD_EN_WIDTH 1
++#define EE_WR_TIMER_ACTIVE_LBN 28
++#define EE_WR_TIMER_ACTIVE_WIDTH 1
++#define EE_SPI_HCMD_SF_SEL_LBN 24
++#define EE_SPI_HCMD_SF_SEL_WIDTH 1
++#define EE_SPI_EEPROM 0
++#define EE_SPI_FLASH 1
++#define EE_SPI_HCMD_DABCNT_LBN 16
++#define EE_SPI_HCMD_DABCNT_WIDTH 5
++#define EE_SPI_HCMD_READ_LBN 15
++#define EE_SPI_HCMD_READ_WIDTH 1
++#define EE_SPI_READ 1
++#define EE_SPI_WRITE 0
++#define EE_SPI_HCMD_DUBCNT_LBN 12
++#define EE_SPI_HCMD_DUBCNT_WIDTH 2
++#define EE_SPI_HCMD_ADBCNT_LBN 8
++#define EE_SPI_HCMD_ADBCNT_WIDTH 2
++#define EE_SPI_HCMD_ENC_LBN 0
++#define EE_SPI_HCMD_ENC_WIDTH 8
++
++/* SPI host address register */
++#define EE_SPI_HADR_REG_KER 0x0110
++#define EE_SPI_HADR_DUBYTE_LBN 24
++#define EE_SPI_HADR_DUBYTE_WIDTH 8
++#define EE_SPI_HADR_ADR_LBN 0
++#define EE_SPI_HADR_ADR_WIDTH 24
++
++/* SPI host data register */
++#define EE_SPI_HDATA_REG_KER 0x0120
++#define EE_SPI_HDATA3_LBN 96
++#define EE_SPI_HDATA3_WIDTH 32
++#define EE_SPI_HDATA2_LBN 64
++#define EE_SPI_HDATA2_WIDTH 32
++#define EE_SPI_HDATA1_LBN 32
++#define EE_SPI_HDATA1_WIDTH 32
++#define EE_SPI_HDATA0_LBN 0
++#define EE_SPI_HDATA0_WIDTH 32
++
++/* SPI/VPD config register */
++#define EE_VPD_CFG_REG_KER 0x0140
++#define EE_VPD_EN_LBN 0
++#define EE_VPD_EN_WIDTH 1
++#define EE_VPD_EN_AD9_MODE_LBN 1
++#define EE_VPD_EN_AD9_MODE_WIDTH 1
++#define EE_EE_CLOCK_DIV_LBN 112
++#define EE_EE_CLOCK_DIV_WIDTH 7
++#define EE_SF_CLOCK_DIV_LBN 120
++#define EE_SF_CLOCK_DIV_WIDTH 7
++
++/* PCIE CORE ACCESS REG */
++#define PCIE_CORE_INDIRECT_REG 0x01f0
++#define PCIE_CORE_ADDR_LBN 0
++#define PCIE_CORE_ADDR_WIDTH 12
++#define PCIE_CORE_RW_LBN 15
++#define PCIE_CORE_RW_WIDTH 1
++#define PCIE_CORE_VALUE_LBN 32
++#define PCIE_CORE_VALUE_WIDTH 32
++
++#define PCIE_CORE_ADDR_PCIE_DEVICE_CTRL_STAT 0x68
++#define PCIE_CORE_ADDR_PCIE_LINK_CTRL_STAT 0x70
++#define PCIE_CORE_ADDR_ACK_RPL_TIMER 0x700
++#define PCIE_CORE_ACK_TL_LBN 0
++#define PCIE_CORE_ACK_TL_WIDTH 16
++#define PCIE_CORE_RPL_TL_LBN 16
++#define PCIE_CORE_RPL_TL_WIDTH 16
++
++#define PCIE_CORE_ADDR_ACK_FREQ 0x70C
++#define PCIE_CORE_ACK_FREQ_LBN 0
++#define PCIE_CORE_ACK_FREQ_WIDTH 7
++
++
++/* NIC status register */
++#define NIC_STAT_REG 0x0200
++#define EE_STRAP_EN_LBN 31
++#define EE_STRAP_EN_WIDTH 1
++#define EE_STRAP_OVR_LBN 24
++#define EE_STRAP_OVR_WIDTH 4
++#define ONCHIP_SRAM_LBN 16
++#define ONCHIP_SRAM_WIDTH 1
++#define SF_PRST_LBN 9
++#define SF_PRST_WIDTH 1
++#define EE_PRST_LBN 8
++#define EE_PRST_WIDTH 1
++#define EE_STRAP_LBN 7
++#define EE_STRAP_WIDTH 1
++/* See pic_mode_t for decoding of this field */
++#define STRAP_ISCSI_EN_LBN 3
++#define STRAP_ISCSI_EN_WIDTH 1
++#define STRAP_PINS_LBN 0
++#define STRAP_PINS_WIDTH 3
++/* These bit definitions are extrapolated from the list of numerical
++ * values for STRAP_PINS.
++ */
++#define STRAP_10G_LBN 2
++#define STRAP_10G_WIDTH 1
++#define STRAP_DUAL_PORT_LBN 1
++#define STRAP_DUAL_PORT_WIDTH 1
++#define STRAP_PCIE_LBN 0
++#define STRAP_PCIE_WIDTH 1
++
++#define FLASH_PRESENT_LBN 7
++#define FLASH_PRESENT_WIDTH 1
++#define EEPROM_PRESENT_LBN 6
++#define EEPROM_PRESENT_WIDTH 1
++#define BOOTED_USING_NVDEVICE_LBN 3
++#define BOOTED_USING_NVDEVICE_WIDTH 1
++
++/* GPIO control register */
++
++#define GPIO_CTL_REG_KER 0x0210
++
++#define GPIO_USE_NIC_CLK_LBN (30)
++#define GPIO_USE_NIC_CLK_WIDTH (1)
++
++#define GPIO_OUTPUTS_LBN (16)
++#define GPIO_OUTPUTS_WIDTH (4)
++
++#define GPIO_INPUTS_LBN (8)
++#define GPIO_INPUT_WIDTH (4)
++
++#define GPIO_DIRECTION_LBN (24)
++#define GPIO_DIRECTION_WIDTH (4)
++#define GPIO_DIRECTION_OUT (1)
++#define GPIO_SRAM_SLEEP (1 << 1)
++
++#define GPIO3_OEN_LBN (GPIO_DIRECTION_LBN + 3)
++#define GPIO3_OEN_WIDTH 1
++#define GPIO2_OEN_LBN (GPIO_DIRECTION_LBN + 2)
++#define GPIO2_OEN_WIDTH 1
++#define GPIO1_OEN_LBN (GPIO_DIRECTION_LBN + 1)
++#define GPIO1_OEN_WIDTH 1
++#define GPIO0_OEN_LBN (GPIO_DIRECTION_LBN + 0)
++#define GPIO0_OEN_WIDTH 1
++
++#define GPIO3_OUT_LBN (GPIO_OUTPUTS_LBN + 3)
++#define GPIO3_OUT_WIDTH 1
++#define GPIO2_OUT_LBN (GPIO_OUTPUTS_LBN + 2)
++#define GPIO2_OUT_WIDTH 1
++#define GPIO1_OUT_LBN (GPIO_OUTPUTS_LBN + 1)
++#define GPIO1_OUT_WIDTH 1
++#define GPIO0_OUT_LBN (GPIO_OUTPUTS_LBN + 0)
++#define GPIO0_OUT_WIDTH 1
++
++#define GPIO3_IN_LBN (GPIO_INPUTS_LBN + 3)
++#define GPIO3_IN_WIDTH 1
++#define GPIO2_IN_LBN (GPIO_INPUTS_LBN + 2)
++#define GPIO2_IN_WIDTH 1
++#define GPIO1_IN_LBN (GPIO_INPUTS_LBN + 1)
++#define GPIO1_IN_WIDTH 1
++#define GPIO0_IN_LBN (GPIO_INPUTS_LBN + 0)
++#define GPIO0_IN_WIDTH 1
++
++/* Global control register */
++#define GLB_CTL_REG_KER 0x0220
++#define EXT_PHY_RST_CTL_LBN 63
++#define EXT_PHY_RST_CTL_WIDTH 1
++#define PCIE_SD_RST_CTL_LBN 61
++#define PCIE_SD_RST_CTL_WIDTH 1
++#define PCIX_RST_CTL_LBN 60
++#define PCIX_RST_CTL_WIDTH 1
++#define PCIE_STCK_RST_CTL_LBN 59
++
++#define PCIE_STCK_RST_CTL_WIDTH 1
++#define PCIE_NSTCK_RST_CTL_LBN 58
++#define PCIE_NSTCK_RST_CTL_WIDTH 1
++#define PCIE_CORE_RST_CTL_LBN 57
++#define PCIE_CORE_RST_CTL_WIDTH 1
++#define EE_RST_CTL_LBN 49
++#define EE_RST_CTL_WIDTH 1
++#define CS_RST_CTL_LBN 48
++#define CS_RST_CTL_WIDTH 1
++#define RST_EXT_PHY_LBN 31
++#define RST_EXT_PHY_WIDTH 1
++#define RST_XGRX_LBN 24
++#define RST_XGRX_WIDTH 1
++#define RST_XGTX_LBN 23
++#define RST_XGTX_WIDTH 1
++#define RST_EM_LBN 22
++#define RST_EM_WIDTH 1
++#define INT_RST_DUR_LBN 4
++#define INT_RST_DUR_WIDTH 3
++#define EXT_PHY_RST_DUR_LBN 1
++#define EXT_PHY_RST_DUR_WIDTH 3
++#define SWRST_LBN 0
++#define SWRST_WIDTH 1
++#define INCLUDE_IN_RESET 0
++#define EXCLUDE_FROM_RESET 1
++
++/* Fatal interrupt register */
++#define FATAL_INTR_REG_KER 0x0230
++#define PCI_BUSERR_INT_KER_EN_LBN 43
++#define PCI_BUSERR_INT_KER_EN_WIDTH 1
++#define SRAM_OOB_INT_KER_EN_LBN 42
++#define SRAM_OOB_INT_KER_EN_WIDTH 1
++#define BUFID_OOB_INT_KER_EN_LBN 41
++#define BUFID_OOB_INT_KER_EN_WIDTH 1
++#define MEM_PERR_INT_KER_EN_LBN 40
++#define MEM_PERR_INT_KER_EN_WIDTH 1
++#define RBUF_OWN_INT_KER_EN_LBN 39
++#define RBUF_OWN_INT_KER_EN_WIDTH 1
++#define TBUF_OWN_INT_KER_EN_LBN 38
++#define TBUF_OWN_INT_KER_EN_WIDTH 1
++#define RDESCQ_OWN_INT_KER_EN_LBN 37
++#define RDESCQ_OWN_INT_KER_EN_WIDTH 1
++#define TDESCQ_OWN_INT_KER_EN_LBN 36
++#define TDESCQ_OWN_INT_KER_EN_WIDTH 1
++#define EVQ_OWN_INT_KER_EN_LBN 35
++#define EVQ_OWN_INT_KER_EN_WIDTH 1
++#define EVFF_OFLO_INT_KER_EN_LBN 34
++#define EVFF_OFLO_INT_KER_EN_WIDTH 1
++#define ILL_ADR_INT_KER_EN_LBN 33
++#define ILL_ADR_INT_KER_EN_WIDTH 1
++#define SRM_PERR_INT_KER_EN_LBN 32
++#define SRM_PERR_INT_KER_EN_WIDTH 1
++#define MEM_PERR_INT_KER_LBN 8
++#define MEM_PERR_INT_KER_WIDTH 1
++#define INT_KER_ERROR_LBN 0
++#define INT_KER_ERROR_WIDTH 12
++
++#define DP_CTRL_REG 0x250
++#define FLS_EVQ_ID_LBN 0
++#define FLS_EVQ_ID_WIDTH 11
++
++#define MEM_STAT_REG_KER 0x260
++
++/* Debug probe register */
++#define DEBUG_REG_KER 0x0270
++#define DEBUG_BLK_SEL2_LBN 47
++#define DEBUG_BLK_SEL2_WIDTH 3
++#define DEBUG_BLK_SEL1_LBN 44
++#define DEBUG_BLK_SEL1_WIDTH 3
++#define DEBUG_BLK_SEL0_LBN 41
++#define DEBUG_BLK_SEL0_WIDTH 3
++#define DEBUG_BLK_SEL_MISC 7
++#define DEBUG_BLK_SEL_SERDES 6
++#define DEBUG_BLK_SEL_EM 5
++#define DEBUG_BLK_SEL_SR 4
++#define DEBUG_BLK_SEL_EV 3
++#define DEBUG_BLK_SEL_RX 2
++#define DEBUG_BLK_SEL_TX 1
++#define DEBUG_BLK_SEL_BIU 0
++#define MISC_DEBUG_ADDR_LBN 36
++#define MISC_DEBUG_ADDR_WIDTH 5
++#define SERDES_DEBUG_ADDR_LBN 31
++#define SERDES_DEBUG_ADDR_WIDTH 5
++#define EM_DEBUG_ADDR_LBN 26
++#define EM_DEBUG_ADDR_WIDTH 5
++#define SR_DEBUG_ADDR_LBN 21
++#define SR_DEBUG_ADDR_WIDTH 5
++#define EV_DEBUG_ADDR_LBN 16
++#define EV_DEBUG_ADDR_WIDTH 5
++#define RX_DEBUG_ADDR_LBN 11
++#define RX_DEBUG_ADDR_WIDTH 5
++#define TX_DEBUG_ADDR_LBN 5
++#define TX_DEBUG_ADDR_WIDTH 5
++#define BIU_DEBUG_ADDR_LBN 1
++#define BIU_DEBUG_ADDR_WIDTH 5
++#define DEBUG_DIS_LBN 0
++#define DEBUG_DIS_WIDTH 1
++
++/* Scratch register 0 */
++#define DRIVER_REG0_KER 0x0280
++#define DRIVER_DW0_LBN 0
++#define DRIVER_DW0_WIDTH 32
++
++/* Scratch register 1 */
++#define DRIVER_REG1_KER 0x0290
++#define DRIVER_DW1_LBN 0
++#define DRIVER_DW1_WIDTH 32
++
++/* Scratch register 2 */
++#define DRIVER_REG2_KER 0x02A0
++#define DRIVER_DW2_LBN 0
++#define DRIVER_DW2_WIDTH 32
++
++/* Scratch register 3 */
++#define DRIVER_REG3_KER 0x02B0
++#define DRIVER_DW3_LBN 0
++#define DRIVER_DW3_WIDTH 32
++
++/* Scratch register 4 */
++#define DRIVER_REG4_KER 0x02C0
++#define DRIVER_DW3_LBN 0
++#define DRIVER_DW3_WIDTH 32
++
++/* Scratch register 5 */
++#define DRIVER_REG5_KER 0x02D0
++#define DRIVER_DW3_LBN 0
++#define DRIVER_DW3_WIDTH 32
++
++/* Scratch register 6 */
++#define DRIVER_REG6_KER 0x02E0
++#define DRIVER_DW3_LBN 0
++#define DRIVER_DW3_WIDTH 32
++
++/* Scratch register 7 */
++#define DRIVER_REG7_KER 0x02F0
++#define DRIVER_DW3_LBN 0
++#define DRIVER_DW3_WIDTH 32
++
++/* FPGA build version */
++#define ALTERA_BUILD_REG_KER 0x0300
++#define VER_MAJOR_LBN 24
++#define VER_MAJOR_WIDTH 8
++#define VER_MINOR_LBN 16
++#define VER_MINOR_WIDTH 8
++#define VER_BUILD_LBN 0
++#define VER_BUILD_WIDTH 16
++#define VER_ALL_LBN 0
++#define VER_ALL_WIDTH 32
++
++/* Spare EEPROM bits register (flash 0x390) */
++#define SPARE_REG_KER 0x310
++#define MEM_PERR_EN_LBN 64
++#define MEM_PERR_EN_WIDTH 38
++#define MEM_PERR_EN_TX_DATA_LBN 72
++#define MEM_PERR_EN_TX_DATA_WIDTH 2
++#define SPARE_EE_BITS_LBN 1
++#define SPARE_EE_BITS_WIDTH 31
++#define PCIE_LEGACY_ENDPOINT_LBN 0
++#define PCIE_LEGACY_ENDPOINT_WIDTH 1
++
++/* Page mapped view of bottom 1024 EVQ RPTRS */
++#define EVQ_RPTR_REG_P0 0x400
++/* Bit definitions are as for the densely mapped
++ * RPTR registers. */
++
++/* Timer table for kernel access */
++#define TIMER_CMD_REG_KER 0x420
++#define TIMER_MODE_LBN 12
++#define TIMER_MODE_WIDTH 2
++#define TIMER_MODE_DIS 0
++#define TIMER_MODE_INT_HLDOFF 2
++#define TIMER_VAL_LBN 0
++#define TIMER_VAL_WIDTH 12
++
++/* Driver generated event register */
++#define DRV_EV_REG_KER 0x440
++#define DRV_EV_QID_LBN 64
++#define DRV_EV_QID_WIDTH 12
++#define DRV_EV_DATA_LBN 0
++#define DRV_EV_DATA_WIDTH 64
++
++/* Event Queue control register */
++#define EVQ_CTL_REG_KER 0x450
++#define EVQ_FIFO_NOTAF_TH_LBN 0
++#define EVQ_FIFO_NOTAF_TH_WIDTH 6
++#define EVQ_FIFO_AF_TH_LBN 8
++#define EVQ_FIFO_AF_TH_WIDTH 6
++
++/* Buffer table configuration register */
++#define BUF_TBL_CFG_REG_KER 0x600
++#define BUF_TBL_MODE_LBN 3
++#define BUF_TBL_MODE_WIDTH 1
++#define BUF_TBL_MODE_HALF 0
++#define BUF_TBL_MODE_FULL 1
++
++/* SRAM receive descriptor cache configuration register */
++#define SRM_RX_DC_CFG_REG_KER 0x610
++#define SRM_RX_DC_BASE_ADR_LBN 0
++#define SRM_RX_DC_BASE_ADR_WIDTH 21
++
++/* SRAM transmit descriptor cache configuration register */
++#define SRM_TX_DC_CFG_REG_KER 0x620
++#define SRM_TX_DC_BASE_ADR_LBN 0
++#define SRM_TX_DC_BASE_ADR_WIDTH 21
++
++/* SRAM configuration register */
++#define SRM_CFG_REG_KER 0x630
++#define SRAM_OOB_ADR_INTEN_LBN 5
++#define SRAM_OOB_ADR_INTEN_WIDTH 1
++#define SRAM_OOB_BUF_INTEN_LBN 4
++#define SRAM_OOB_BUF_INTEN_WIDTH 1
++#define SRAM_OOB_BT_INIT_EN_LBN 3
++#define SRAM_OOB_BT_INIT_EN_WIDTH 1
++#define SRM_NUM_BANK_LBN 2
++#define SRM_NUM_BANK_WIDTH 1
++#define SRM_BANK_SIZE_LBN 0
++#define SRM_BANK_SIZE_WIDTH 2
++#define SRM_NUM_BANKS_AND_BANK_SIZE_LBN 0
++#define SRM_NUM_BANKS_AND_BANK_SIZE_WIDTH 3
++#define SRM_NB_BSZ_1BANKS_2M 0
++#define SRM_NB_BSZ_1BANKS_4M 1
++#define SRM_NB_BSZ_1BANKS_8M 2
++#define SRM_NB_BSZ_DEFAULT 3 /* char driver will set the default */
++#define SRM_NB_BSZ_2BANKS_4M 4
++#define SRM_NB_BSZ_2BANKS_8M 5
++#define SRM_NB_BSZ_2BANKS_16M 6
++#define SRM_NB_BSZ_RESERVED 7
++
++/* Special buffer table update register */
++#define BUF_TBL_UPD_REG_KER 0x0650
++#define BUF_UPD_CMD_LBN 63
++#define BUF_UPD_CMD_WIDTH 1
++#define BUF_CLR_CMD_LBN 62
++#define BUF_CLR_CMD_WIDTH 1
++#define BUF_CLR_END_ID_LBN 32
++#define BUF_CLR_END_ID_WIDTH 20
++#define BUF_CLR_START_ID_LBN 0
++#define BUF_CLR_START_ID_WIDTH 20
++
++/* Receive configuration register */
++#define RX_CFG_REG_KER 0x800
++
++/* B0 */
++#define RX_TOEP_TCP_SUPPRESS_B0_LBN 48
++#define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++#define RX_INGR_EN_B0_LBN 47
++#define RX_INGR_EN_B0_WIDTH 1
++#define RX_TOEP_IPV4_B0_LBN 46
++#define RX_TOEP_IPV4_B0_WIDTH 1
++#define RX_HASH_ALG_B0_LBN 45
++#define RX_HASH_ALG_B0_WIDTH 1
++#define RX_HASH_INSERT_HDR_B0_LBN 44
++#define RX_HASH_INSERT_HDR_B0_WIDTH 1
++#define RX_DESC_PUSH_EN_B0_LBN 43
++#define RX_DESC_PUSH_EN_B0_WIDTH 1
++#define RX_RDW_PATCH_EN_LBN 42 /* Non head of line blocking */
++#define RX_RDW_PATCH_EN_WIDTH 1
++#define RX_PCI_BURST_SIZE_B0_LBN 39
++#define RX_PCI_BURST_SIZE_B0_WIDTH 3
++#define RX_OWNERR_CTL_B0_LBN 38
++#define RX_OWNERR_CTL_B0_WIDTH 1
++#define RX_XON_TX_TH_B0_LBN 33
++#define RX_XON_TX_TH_B0_WIDTH 5
++#define RX_XOFF_TX_TH_B0_LBN 28
++#define RX_XOFF_TX_TH_B0_WIDTH 5
++#define RX_USR_BUF_SIZE_B0_LBN 19
++#define RX_USR_BUF_SIZE_B0_WIDTH 9
++#define RX_XON_MAC_TH_B0_LBN 10
++#define RX_XON_MAC_TH_B0_WIDTH 9
++#define RX_XOFF_MAC_TH_B0_LBN 1
++#define RX_XOFF_MAC_TH_B0_WIDTH 9
++#define RX_XOFF_MAC_EN_B0_LBN 0
++#define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++/* A1 */
++#define RX_DESC_PUSH_EN_A1_LBN 35
++#define RX_DESC_PUSH_EN_A1_WIDTH 1
++#define RX_PCI_BURST_SIZE_A1_LBN 31
++#define RX_PCI_BURST_SIZE_A1_WIDTH 3
++#define RX_OWNERR_CTL_A1_LBN 30
++#define RX_OWNERR_CTL_A1_WIDTH 1
++#define RX_XON_TX_TH_A1_LBN 25
++#define RX_XON_TX_TH_A1_WIDTH 5
++#define RX_XOFF_TX_TH_A1_LBN 20
++#define RX_XOFF_TX_TH_A1_WIDTH 5
++#define RX_USR_BUF_SIZE_A1_LBN 11
++#define RX_USR_BUF_SIZE_A1_WIDTH 9
++#define RX_XON_MAC_TH_A1_LBN 6
++#define RX_XON_MAC_TH_A1_WIDTH 5
++#define RX_XOFF_MAC_TH_A1_LBN 1
++#define RX_XOFF_MAC_TH_A1_WIDTH 5
++#define RX_XOFF_MAC_EN_A1_LBN 0
++#define RX_XOFF_MAC_EN_A1_WIDTH 1
++
++/* Receive filter control register */
++#define RX_FILTER_CTL_REG 0x810
++#define SCATTER_ENBL_NO_MATCH_Q_B0_LBN 40
++#define SCATTER_ENBL_NO_MATCH_Q_B0_WIDTH 1
++#define UDP_FULL_SRCH_LIMIT_LBN 32
++#define UDP_FULL_SRCH_LIMIT_WIDTH 8
++#define NUM_KER_LBN 24
++#define NUM_KER_WIDTH 2
++#define UDP_WILD_SRCH_LIMIT_LBN 16
++#define UDP_WILD_SRCH_LIMIT_WIDTH 8
++#define TCP_WILD_SRCH_LIMIT_LBN 8
++#define TCP_WILD_SRCH_LIMIT_WIDTH 8
++#define TCP_FULL_SRCH_LIMIT_LBN 0
++#define TCP_FULL_SRCH_LIMIT_WIDTH 8
++
++/* RX queue flush register */
++#define RX_FLUSH_DESCQ_REG_KER 0x0820
++#define RX_FLUSH_DESCQ_CMD_LBN 24
++#define RX_FLUSH_DESCQ_CMD_WIDTH 1
++#define RX_FLUSH_DESCQ_LBN 0
++#define RX_FLUSH_DESCQ_WIDTH 12
++
++/* Receive descriptor update register */
++#define RX_DESC_UPD_REG_KER 0x0830
++#define RX_DESC_WPTR_LBN 96
++#define RX_DESC_WPTR_WIDTH 12
++#define RX_DESC_UPD_REG_KER_DWORD (RX_DESC_UPD_REG_KER + 12)
++#define RX_DESC_WPTR_DWORD_LBN 0
++#define RX_DESC_WPTR_DWORD_WIDTH 12
++
++/* Receive descriptor cache configuration register */
++#define RX_DC_CFG_REG_KER 0x840
++#define RX_DC_SIZE_LBN 0
++#define RX_DC_SIZE_WIDTH 2
++
++#define RX_DC_PF_WM_REG_KER 0x850
++#define RX_DC_PF_LWM_LBN 0
++#define RX_DC_PF_LWM_WIDTH 6
++
++/* RX no descriptor drop counter */
++#define RX_NODESC_DROP_REG_KER 0x880
++#define RX_NODESC_DROP_CNT_LBN 0
++#define RX_NODESC_DROP_CNT_WIDTH 16
++
++/* RX black magic register */
++#define RX_SELF_RST_REG_KER 0x890
++#define RX_ISCSI_DIS_LBN 17
++#define RX_ISCSI_DIS_WIDTH 1
++#define RX_PREFETCH_TIMEOUT_EN_LBN 10
++#define RX_PREFETCH_TIMEOUT_EN_WIDTH 1
++#define RX_NODESC_WAIT_DIS_LBN 9
++#define RX_NODESC_WAIT_DIS_WIDTH 1
++#define RX_RECOVERY_EN_LBN 8
++#define RX_RECOVERY_EN_WIDTH 1
++#define RX_SHUTDOWN_REASON_LBN 0
++#define RX_SHUTDOWN_REASON_WIDTH (3)
++
++/* TX queue flush register */
++#define TX_FLUSH_DESCQ_REG_KER 0x0a00
++#define TX_FLUSH_DESCQ_CMD_LBN 12
++#define TX_FLUSH_DESCQ_CMD_WIDTH 1
++#define TX_FLUSH_DESCQ_LBN 0
++#define TX_FLUSH_DESCQ_WIDTH 12
++
++/* Transmit descriptor update register */
++#define TX_DESC_UPD_REG_KER 0x0a10
++#define TX_DESC_WPTR_LBN 96
++#define TX_DESC_WPTR_WIDTH 12
++#define TX_DESC_UPD_REG_KER_DWORD (TX_DESC_UPD_REG_KER + 12)
++#define TX_DESC_WPTR_DWORD_LBN 0
++#define TX_DESC_WPTR_DWORD_WIDTH 12
++
++/* Transmit descriptor cache configuration register */
++#define TX_DC_CFG_REG_KER 0xa20
++#define TX_DC_SIZE_LBN 0
++#define TX_DC_SIZE_WIDTH 2
++
++/* Transmit checksum configuration register (A0/A1 only) */
++#define TX_CHKSM_CFG_REG_KER_A1 0xa30
++
++/* Transmit configuration register */
++#define TX_CFG_REG_KER 0xa50
++#define TX_NO_EOP_DISC_EN_LBN 5
++#define TX_NO_EOP_DISC_EN_WIDTH 1
++
++/* Transmit configuration register 2 */
++#define TX_CFG2_REG_KER 0xa80
++#define TX_CSR_PUSH_EN_LBN 89
++#define TX_CSR_PUSH_EN_WIDTH 1
++#define TX_RX_SPACER_LBN 64
++#define TX_RX_SPACER_WIDTH 8
++#define TX_SW_EV_EN_LBN 59
++#define TX_SW_EV_EN_WIDTH 1
++#define TX_RX_SPACER_EN_LBN 57
++#define TX_RX_SPACER_EN_WIDTH 1
++#define TX_PREF_WD_TMR_LBN 22
++#define TX_PREF_WD_TMR_WIDTH 22
++#define TX_PREF_THRESHOLD_LBN 19
++#define TX_PREF_THRESHOLD_WIDTH 2
++#define TX_ONE_PKT_PER_Q_LBN 18
++#define TX_ONE_PKT_PER_Q_WIDTH 1
++#define TX_DIS_NON_IP_EV_LBN 17
++#define TX_DIS_NON_IP_EV_WIDTH 1
++#define TX_DMA_SPACER_LBN 8
++#define TX_DMA_SPACER_WIDTH 8
++#define TX_FLUSH_MIN_LEN_EN_B0_LBN 7
++#define TX_FLUSH_MIN_LEN_EN_B0_WIDTH 1
++#define TX_TCP_DIS_A1_LBN 7
++#define TX_TCP_DIS_A1_WIDTH 1
++#define TX_IP_DIS_A1_LBN 6
++#define TX_IP_DIS_A1_WIDTH 1
++#define TX_MAX_CPL_LBN 2
++#define TX_MAX_CPL_WIDTH 2
++#define TX_MAX_PREF_LBN 0
++#define TX_MAX_PREF_WIDTH 2
++
++/* Transmit VLAN filter control register */
++#define TX_VLAN_REG 0xae0
++
++/* PHY management transmit data register */
++#define MD_TXD_REG_KER 0xc00
++#define MD_TXD_LBN 0
++#define MD_TXD_WIDTH 16
++
++/* PHY management receive data register */
++#define MD_RXD_REG_KER 0xc10
++#define MD_RXD_LBN 0
++#define MD_RXD_WIDTH 16
++
++/* PHY management configuration & status register */
++#define MD_CS_REG_KER 0xc20
++#define MD_PT_LBN 7
++#define MD_PT_WIDTH 3
++#define MD_PL_LBN 6
++#define MD_PL_WIDTH 1
++#define MD_INT_CLR_LBN 5
++#define MD_INT_CLR_WIDTH 1
++#define MD_GC_LBN 4
++#define MD_GC_WIDTH 1
++#define MD_PRSP_LBN 3
++#define MD_PRSP_WIDTH 1
++#define MD_RIC_LBN 2
++#define MD_RIC_WIDTH 1
++#define MD_RDC_LBN 1
++#define MD_RDC_WIDTH 1
++#define MD_WRC_LBN 0
++#define MD_WRC_WIDTH 1
++
++/* PHY management PHY address register */
++#define MD_PHY_ADR_REG_KER 0xc30
++#define MD_PHY_ADR_LBN 0
++#define MD_PHY_ADR_WIDTH 16
++
++/* PHY management ID register */
++#define MD_ID_REG_KER 0xc40
++#define MD_PRT_ADR_LBN 11
++#define MD_PRT_ADR_WIDTH 5
++#define MD_DEV_ADR_LBN 6
++#define MD_DEV_ADR_WIDTH 5
++/* Used for writing both at once */
++#define MD_PRT_DEV_ADR_LBN 6
++#define MD_PRT_DEV_ADR_WIDTH 10
++
++/* PHY management status & mask register (DWORD read only) */
++#define MD_STAT_REG_KER 0xc50
++#define MD_PINT_LBN 4
++#define MD_PINT_WIDTH 1
++#define MD_DONE_LBN 3
++#define MD_DONE_WIDTH 1
++#define MD_BSERR_LBN 2
++#define MD_BSERR_WIDTH 1
++#define MD_LNFL_LBN 1
++#define MD_LNFL_WIDTH 1
++#define MD_BSY_LBN 0
++#define MD_BSY_WIDTH 1
++
++/* Port 0 and 1 MAC stats registers */
++#define MAC0_STAT_DMA_REG_KER 0xc60
++#define MAC1_STAT_DMA_REG_KER 0xc70
++#define MAC_STAT_DMA_CMD_LBN 48
++#define MAC_STAT_DMA_CMD_WIDTH 1
++#define MAC_STAT_DMA_REGION_LBN 46
++#define MAC_STAT_DMA_REGION_WIDTH 2
++#define MAC_STAT_DMA_ADR_LBN 0
++#define MAC_STAT_DMA_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46)
++
++/* Port 0 and 1 MAC control registers */
++#define MAC0_CTRL_REG_KER 0xc80
++#define MAC1_CTRL_REG_KER 0xc90
++#define MAC_XOFF_VAL_LBN 16
++#define MAC_XOFF_VAL_WIDTH 16
++#define TXFIFO_DRAIN_EN_B0_LBN 7
++#define TXFIFO_DRAIN_EN_B0_WIDTH 1
++#define MAC_XG_DISTXCRC_LBN 5
++#define MAC_XG_DISTXCRC_WIDTH 1
++#define MAC_BCAD_ACPT_LBN 4
++#define MAC_BCAD_ACPT_WIDTH 1
++#define MAC_UC_PROM_LBN 3
++#define MAC_UC_PROM_WIDTH 1
++#define MAC_LINK_STATUS_LBN 2
++#define MAC_LINK_STATUS_WIDTH 1
++#define MAC_SPEED_LBN 0
++#define MAC_SPEED_WIDTH 2
++
++/* External interrupt control (replaces MAC1_CTRL in B0) */
++#define GEN_MODE_REG_KER 0xc90
++#define XFP_PHY_INT_POL_SEL_LBN 3
++#define XFP_PHY_INT_POL_SEL_WIDTH 1
++#define XG_PHY_INT_POL_SEL_LBN 2
++#define XG_PHY_INT_POL_SEL_WIDTH 1
++#define XFP_PHY_INT_MASK_LBN 1
++#define XFP_PHY_INT_MASK_WIDTH 1
++#define XG_PHY_INT_MASK_LBN 0
++#define XG_PHY_INT_MASK_WIDTH 1
++
++
++/* 10G XAUI XGXS default values */
++#define XX_TXDRV_DEQ_DEFAULT 0xe /* deq=.6 */
++#define XX_TXDRV_DTX_DEFAULT 0x5 /* 1.25 */
++#define XX_SD_CTL_DRV_DEFAULT 0 /* 20mA */
++
++/* Multicast address hash table */
++#define MAC_MCAST_HASH_REG0_KER 0xca0
++#define MAC_MCAST_HASH_REG1_KER 0xcb0
++
++/* MAC test register. */
++#define MAC_TEST_REG_KER 0xcc0
++#define MAC_PTLOOP_EN_LBN 0
++#define MAC_PTLOOP_EN_WIDTH 1
++
++/* GMAC registers */
++#define FALCON_GMAC_REGBANK 0xe00
++#define FALCON_GMAC_REGBANK_SIZE 0x200
++#define FALCON_GMAC_REG_SIZE 0x10
++
++/* Source MAC filter control register */
++#define TX_SRC_MAC_CTRL_REG 0x1100
++
++/* XMAC registers */
++#define FALCON_XMAC_REGBANK 0x1200
++#define FALCON_XMAC_REGBANK_SIZE 0x200
++#define FALCON_XMAC_REG_SIZE 0x10
++
++/* XGMAC address register low */
++#define XM_ADR_LO_REG_MAC 0x00
++#define XM_ADR_3_LBN 24
++#define XM_ADR_3_WIDTH 8
++#define XM_ADR_2_LBN 16
++#define XM_ADR_2_WIDTH 8
++#define XM_ADR_1_LBN 8
++#define XM_ADR_1_WIDTH 8
++#define XM_ADR_0_LBN 0
++#define XM_ADR_0_WIDTH 8
++
++/* XGMAC address register high */
++#define XM_ADR_HI_REG_MAC 0x01
++#define XM_ADR_5_LBN 8
++#define XM_ADR_5_WIDTH 8
++#define XM_ADR_4_LBN 0
++#define XM_ADR_4_WIDTH 8
++
++/* XGMAC global configuration */
++#define XM_GLB_CFG_REG_MAC 0x02
++#define XM_LINE_LB_DEEP_RSVD_LBN 28
++#define XM_LINE_LB_DEEP_RSVD_WIDTH 1
++#define XM_RMTFLT_GEN_LBN 17
++#define XM_RMTFLT_GEN_WIDTH 1
++#define XM_DEBUG_MODE_LBN 16
++#define XM_DEBUG_MODE_WIDTH 1
++#define XM_RX_STAT_EN_LBN 11
++#define XM_RX_STAT_EN_WIDTH 1
++#define XM_TX_STAT_EN_LBN 10
++#define XM_TX_STAT_EN_WIDTH 1
++#define XM_RX_JUMBO_MODE_LBN 6
++#define XM_RX_JUMBO_MODE_WIDTH 1
++#define XM_WAN_MODE_LBN 5
++#define XM_WAN_MODE_WIDTH 1
++#define XM_AUTOCLR_MODE_LBN 4
++#define XM_AUTOCLR_MODE_WIDTH 1
++#define XM_INTCLR_MODE_LBN 3
++#define XM_INTCLR_MODE_WIDTH 1
++#define XM_CORE_RST_LBN 0
++#define XM_CORE_RST_WIDTH 1
++
++/* XGMAC transmit configuration */
++#define XM_TX_CFG_REG_MAC 0x03
++#define XM_TX_PROG_LBN 24
++#define XM_TX_PROG_WIDTH 1
++#define XM_IPG_LBN 16
++#define XM_IPG_WIDTH 4
++#define XM_FCNTL_LBN 10
++#define XM_FCNTL_WIDTH 1
++#define XM_TXCRC_LBN 8
++#define XM_TXCRC_WIDTH 1
++#define XM_EDRC_LBN 6
++#define XM_EDRC_WIDTH 1
++#define XM_AUTO_PAD_LBN 5
++#define XM_AUTO_PAD_WIDTH 1
++#define XM_TX_PRMBL_LBN 2
++#define XM_TX_PRMBL_WIDTH 1
++#define XM_TXEN_LBN 1
++#define XM_TXEN_WIDTH 1
++#define XM_TX_RST_LBN 0
++#define XM_TX_RST_WIDTH 1
++
++/* XGMAC receive configuration */
++#define XM_RX_CFG_REG_MAC 0x04
++#define XM_PASS_LENERR_LBN 26
++#define XM_PASS_LENERR_WIDTH 1
++#define XM_PASS_CRC_ERR_LBN 25
++#define XM_PASS_CRC_ERR_WIDTH 1
++#define XM_PASS_PRMBLE_ERR_LBN 24
++#define XM_PASS_PRMBLE_ERR_WIDTH 1
++#define XM_ACPT_ALL_MCAST_LBN 11
++#define XM_ACPT_ALL_MCAST_WIDTH 1
++#define XM_ACPT_ALL_UCAST_LBN 9
++#define XM_ACPT_ALL_UCAST_WIDTH 1
++#define XM_AUTO_DEPAD_LBN 8
++#define XM_AUTO_DEPAD_WIDTH 1
++#define XM_RXCRC_LBN 3
++#define XM_RXCRC_WIDTH 1
++#define XM_RX_PRMBL_LBN 2
++#define XM_RX_PRMBL_WIDTH 1
++#define XM_RXEN_LBN 1
++#define XM_RXEN_WIDTH 1
++#define XM_RX_RST_LBN 0
++#define XM_RX_RST_WIDTH 1
++
++/* XGMAC flow control register */
++#define XM_FC_REG_MAC 0x7
++#define XM_PAUSE_TIME_LBN 16
++#define XM_PAUSE_TIME_WIDTH 16
++#define XM_DIS_FCNTL_LBN 0
++#define XM_DIS_FCNTL_WIDTH 1
++
++/* XGMAC pause time count register */
++#define XM_PAUSE_TIME_REG_MAC 0x9
++#define XM_TX_PAUSE_CNT_LBN 16
++#define XM_TX_PAUSE_CNT_WIDTH 16
++#define XM_RX_PAUSE_CNT_LBN 0
++#define XM_RX_PAUSE_CNT_WIDTH 16
++
++/* XGMAC transmit parameter register */
++#define XM_TX_PARAM_REG_MAC 0x0d
++#define XM_TX_JUMBO_MODE_LBN 31
++#define XM_TX_JUMBO_MODE_WIDTH 1
++#define XM_MAX_TX_FRM_SIZE_LBN 16
++#define XM_MAX_TX_FRM_SIZE_WIDTH 14
++#define XM_PAD_CHAR_LBN 0
++#define XM_PAD_CHAR_WIDTH 8
++
++/* XGMAC receive parameter register */
++#define XM_RX_PARAM_REG_MAC 0x0e
++#define XM_MAX_RX_FRM_SIZE_LBN 0
++#define XM_MAX_RX_FRM_SIZE_WIDTH 14
++
++/* XGXS/XAUI powerdown/reset register */
++#define XX_PWR_RST_REG_MAC 0x10
++
++#define XX_PWRDND_EN_LBN 15
++#define XX_PWRDND_EN_WIDTH 1
++#define XX_PWRDNC_EN_LBN 14
++#define XX_PWRDNC_EN_WIDTH 1
++#define XX_PWRDNB_EN_LBN 13
++#define XX_PWRDNB_EN_WIDTH 1
++#define XX_PWRDNA_EN_LBN 12
++#define XX_PWRDNA_EN_WIDTH 1
++#define XX_RSTPLLCD_EN_LBN 9
++#define XX_RSTPLLCD_EN_WIDTH 1
++#define XX_RSTPLLAB_EN_LBN 8
++#define XX_RSTPLLAB_EN_WIDTH 1
++#define XX_RESETD_EN_LBN 7
++#define XX_RESETD_EN_WIDTH 1
++#define XX_RESETC_EN_LBN 6
++#define XX_RESETC_EN_WIDTH 1
++#define XX_RESETB_EN_LBN 5
++#define XX_RESETB_EN_WIDTH 1
++#define XX_RESETA_EN_LBN 4
++#define XX_RESETA_EN_WIDTH 1
++#define XX_RSTXGXSRX_EN_LBN 2
++#define XX_RSTXGXSRX_EN_WIDTH 1
++#define XX_RSTXGXSTX_EN_LBN 1
++#define XX_RSTXGXSTX_EN_WIDTH 1
++#define XX_RST_XX_EN_LBN 0
++#define XX_RST_XX_EN_WIDTH 1
++
++/* XGXS/XAUI powerdown/reset control register */
++#define XX_SD_CTL_REG_MAC 0x11
++#define XX_TERMADJ1_LBN 17
++#define XX_TERMADJ1_WIDTH 1
++#define XX_TERMADJ0_LBN 16
++#define XX_TERMADJ0_WIDTH 1
++#define XX_HIDRVD_LBN 15
++#define XX_HIDRVD_WIDTH 1
++#define XX_LODRVD_LBN 14
++#define XX_LODRVD_WIDTH 1
++#define XX_HIDRVC_LBN 13
++#define XX_HIDRVC_WIDTH 1
++#define XX_LODRVC_LBN 12
++#define XX_LODRVC_WIDTH 1
++#define XX_HIDRVB_LBN 11
++#define XX_HIDRVB_WIDTH 1
++#define XX_LODRVB_LBN 10
++#define XX_LODRVB_WIDTH 1
++#define XX_HIDRVA_LBN 9
++#define XX_HIDRVA_WIDTH 1
++#define XX_LODRVA_LBN 8
++#define XX_LODRVA_WIDTH 1
++#define XX_LPBKD_LBN 3
++#define XX_LPBKD_WIDTH 1
++#define XX_LPBKC_LBN 2
++#define XX_LPBKC_WIDTH 1
++#define XX_LPBKB_LBN 1
++#define XX_LPBKB_WIDTH 1
++#define XX_LPBKA_LBN 0
++#define XX_LPBKA_WIDTH 1
++
++#define XX_TXDRV_CTL_REG_MAC 0x12
++#define XX_DEQD_LBN 28
++#define XX_DEQD_WIDTH 4
++#define XX_DEQC_LBN 24
++#define XX_DEQC_WIDTH 4
++#define XX_DEQB_LBN 20
++#define XX_DEQB_WIDTH 4
++#define XX_DEQA_LBN 16
++#define XX_DEQA_WIDTH 4
++#define XX_DTXD_LBN 12
++#define XX_DTXD_WIDTH 4
++#define XX_DTXC_LBN 8
++#define XX_DTXC_WIDTH 4
++#define XX_DTXB_LBN 4
++#define XX_DTXB_WIDTH 4
++#define XX_DTXA_LBN 0
++#define XX_DTXA_WIDTH 4
++
++/* XAUI XGXS core status register */
++#define XX_FORCE_SIG_LBN 24
++#define XX_FORCE_SIG_WIDTH 8
++#define XX_FORCE_SIG_DECODE_FORCED 0xff
++#define XX_XGXS_LB_EN_LBN 23
++#define XX_XGXS_LB_EN_WIDTH 1
++#define XX_XGMII_LB_EN_LBN 22
++#define XX_XGMII_LB_EN_WIDTH 1
++#define XX_CORE_STAT_REG_MAC 0x16
++#define XX_ALIGN_DONE_LBN 20
++#define XX_ALIGN_DONE_WIDTH 1
++#define XX_SYNC_STAT_LBN 16
++#define XX_SYNC_STAT_WIDTH 4
++#define XX_SYNC_STAT_DECODE_SYNCED 0xf
++#define XX_COMMA_DET_LBN 12
++#define XX_COMMA_DET_WIDTH 4
++#define XX_COMMA_DET_DECODE_DETECTED 0xf
++#define XX_COMMA_DET_RESET 0xf
++#define XX_CHARERR_LBN 4
++#define XX_CHARERR_WIDTH 4
++#define XX_CHARERR_RESET 0xf
++#define XX_DISPERR_LBN 0
++#define XX_DISPERR_WIDTH 4
++#define XX_DISPERR_RESET 0xf
++
++/* Receive filter table */
++#define RX_FILTER_TBL0 0xF00000
++
++/* Receive descriptor pointer table */
++#define RX_DESC_PTR_TBL_KER_A1 0x11800
++#define RX_DESC_PTR_TBL_KER_B0 0xF40000
++#define RX_DESC_PTR_TBL_KER_P0 0x900
++#define RX_ISCSI_DDIG_EN_LBN 88
++#define RX_ISCSI_DDIG_EN_WIDTH 1
++#define RX_ISCSI_HDIG_EN_LBN 87
++#define RX_ISCSI_HDIG_EN_WIDTH 1
++#define RX_DESC_PREF_ACT_LBN 86
++#define RX_DESC_PREF_ACT_WIDTH 1
++#define RX_DC_HW_RPTR_LBN 80
++#define RX_DC_HW_RPTR_WIDTH 6
++#define RX_DESCQ_HW_RPTR_LBN 68
++#define RX_DESCQ_HW_RPTR_WIDTH 12
++#define RX_DESCQ_SW_WPTR_LBN 56
++#define RX_DESCQ_SW_WPTR_WIDTH 12
++#define RX_DESCQ_BUF_BASE_ID_LBN 36
++#define RX_DESCQ_BUF_BASE_ID_WIDTH 20
++#define RX_DESCQ_EVQ_ID_LBN 24
++#define RX_DESCQ_EVQ_ID_WIDTH 12
++#define RX_DESCQ_OWNER_ID_LBN 10
++#define RX_DESCQ_OWNER_ID_WIDTH 14
++#define RX_DESCQ_LABEL_LBN 5
++#define RX_DESCQ_LABEL_WIDTH 5
++#define RX_DESCQ_SIZE_LBN 3
++#define RX_DESCQ_SIZE_WIDTH 2
++#define RX_DESCQ_SIZE_4K 3
++#define RX_DESCQ_SIZE_2K 2
++#define RX_DESCQ_SIZE_1K 1
++#define RX_DESCQ_SIZE_512 0
++#define RX_DESCQ_TYPE_LBN 2
++#define RX_DESCQ_TYPE_WIDTH 1
++#define RX_DESCQ_JUMBO_LBN 1
++#define RX_DESCQ_JUMBO_WIDTH 1
++#define RX_DESCQ_EN_LBN 0
++#define RX_DESCQ_EN_WIDTH 1
++
++/* Transmit descriptor pointer table */
++#define TX_DESC_PTR_TBL_KER_A1 0x11900
++#define TX_DESC_PTR_TBL_KER_B0 0xF50000
++#define TX_DESC_PTR_TBL_KER_P0 0xa40
++#define TX_NON_IP_DROP_DIS_B0_LBN 91
++#define TX_NON_IP_DROP_DIS_B0_WIDTH 1
++#define TX_IP_CHKSM_DIS_B0_LBN 90
++#define TX_IP_CHKSM_DIS_B0_WIDTH 1
++#define TX_TCP_CHKSM_DIS_B0_LBN 89
++#define TX_TCP_CHKSM_DIS_B0_WIDTH 1
++#define TX_DESCQ_EN_LBN 88
++#define TX_DESCQ_EN_WIDTH 1
++#define TX_ISCSI_DDIG_EN_LBN 87
++#define TX_ISCSI_DDIG_EN_WIDTH 1
++#define TX_ISCSI_HDIG_EN_LBN 86
++#define TX_ISCSI_HDIG_EN_WIDTH 1
++#define TX_DC_HW_RPTR_LBN 80
++#define TX_DC_HW_RPTR_WIDTH 6
++#define TX_DESCQ_HW_RPTR_LBN 68
++#define TX_DESCQ_HW_RPTR_WIDTH 12
++#define TX_DESCQ_SW_WPTR_LBN 56
++#define TX_DESCQ_SW_WPTR_WIDTH 12
++#define TX_DESCQ_BUF_BASE_ID_LBN 36
++#define TX_DESCQ_BUF_BASE_ID_WIDTH 20
++#define TX_DESCQ_EVQ_ID_LBN 24
++#define TX_DESCQ_EVQ_ID_WIDTH 12
++#define TX_DESCQ_OWNER_ID_LBN 10
++#define TX_DESCQ_OWNER_ID_WIDTH 14
++#define TX_DESCQ_LABEL_LBN 5
++#define TX_DESCQ_LABEL_WIDTH 5
++#define TX_DESCQ_SIZE_LBN 3
++#define TX_DESCQ_SIZE_WIDTH 2
++#define TX_DESCQ_SIZE_4K 3
++#define TX_DESCQ_SIZE_2K 2
++#define TX_DESCQ_SIZE_1K 1
++#define TX_DESCQ_SIZE_512 0
++#define TX_DESCQ_TYPE_LBN 1
++#define TX_DESCQ_TYPE_WIDTH 2
++#define TX_DESCQ_FLUSH_LBN 0
++#define TX_DESCQ_FLUSH_WIDTH 1
++
++/* Event queue pointer */
++#define EVQ_PTR_TBL_KER_A1 0x11a00
++#define EVQ_PTR_TBL_KER_B0 0xf60000
++#define EVQ_PTR_TBL_KER_P0 0x500
++#define EVQ_WKUP_OR_INT_EN_LBN 39
++#define EVQ_WKUP_OR_INT_EN_WIDTH 1
++#define EVQ_NXT_WPTR_LBN 24
++#define EVQ_NXT_WPTR_WIDTH 15
++#define EVQ_EN_LBN 23
++#define EVQ_EN_WIDTH 1
++#define EVQ_SIZE_LBN 20
++#define EVQ_SIZE_WIDTH 3
++#define EVQ_SIZE_32K 6
++#define EVQ_SIZE_16K 5
++#define EVQ_SIZE_8K 4
++#define EVQ_SIZE_4K 3
++#define EVQ_SIZE_2K 2
++#define EVQ_SIZE_1K 1
++#define EVQ_SIZE_512 0
++#define EVQ_BUF_BASE_ID_LBN 0
++#define EVQ_BUF_BASE_ID_WIDTH 20
++
++/* Event queue read pointer */
++#define EVQ_RPTR_REG_KER_A1 0x11b00
++#define EVQ_RPTR_REG_KER_B0 0xfa0000
++#define EVQ_RPTR_LBN 0
++#define EVQ_RPTR_WIDTH 14
++#define EVQ_RPTR_REG_KER_DWORD (EVQ_RPTR_REG_KER + 0)
++#define EVQ_RPTR_DWORD_LBN 0
++#define EVQ_RPTR_DWORD_WIDTH 14
++
++/* RSS indirection table */
++#define RX_RSS_INDIR_TBL_B0 0xFB0000
++#define RX_RSS_INDIR_ENT_B0_LBN 0
++#define RX_RSS_INDIR_ENT_B0_WIDTH 6
++
++/* Special buffer descriptors (full-mode) */
++#define BUF_FULL_TBL_KER_A1 0x8000
++#define BUF_FULL_TBL_KER_B0 0x800000
++#define IP_DAT_BUF_SIZE_LBN 50
++#define IP_DAT_BUF_SIZE_WIDTH 1
++#define IP_DAT_BUF_SIZE_8K 1
++#define IP_DAT_BUF_SIZE_4K 0
++#define BUF_ADR_REGION_LBN 48
++#define BUF_ADR_REGION_WIDTH 2
++#define BUF_ADR_FBUF_LBN 14
++#define BUF_ADR_FBUF_WIDTH 34
++#define BUF_OWNER_ID_FBUF_LBN 0
++#define BUF_OWNER_ID_FBUF_WIDTH 14
++
++/* Special buffer descriptors (half-mode) */
++#define BUF_HALF_TBL_KER_A1 0x8000
++#define BUF_HALF_TBL_KER_B0 0x800000
++#define BUF_ADR_HBUF_ODD_LBN 44
++#define BUF_ADR_HBUF_ODD_WIDTH 20
++#define BUF_OWNER_ID_HBUF_ODD_LBN 32
++#define BUF_OWNER_ID_HBUF_ODD_WIDTH 12
++#define BUF_ADR_HBUF_EVEN_LBN 12
++#define BUF_ADR_HBUF_EVEN_WIDTH 20
++#define BUF_OWNER_ID_HBUF_EVEN_LBN 0
++#define BUF_OWNER_ID_HBUF_EVEN_WIDTH 12
++
++#define SRM_DBG_REG_B0 0x3000000
++
++/* Transmit descriptor */
++#define TX_KER_PORT_LBN 63
++#define TX_KER_PORT_WIDTH 1
++#define TX_KER_CONT_LBN 62
++#define TX_KER_CONT_WIDTH 1
++#define TX_KER_BYTE_CNT_LBN 48
++#define TX_KER_BYTE_CNT_WIDTH 14
++#define TX_KER_BUF_REGION_LBN 46
++#define TX_KER_BUF_REGION_WIDTH 2
++#define TX_KER_BUF_REGION0_DECODE 0
++#define TX_KER_BUF_REGION1_DECODE 1
++#define TX_KER_BUF_REGION2_DECODE 2
++#define TX_KER_BUF_REGION3_DECODE 3
++#define TX_KER_BUF_ADR_LBN 0
++#define TX_KER_BUF_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46)
++
++/* Receive descriptor */
++#define RX_KER_BUF_SIZE_LBN 48
++#define RX_KER_BUF_SIZE_WIDTH 14
++#define RX_KER_BUF_REGION_LBN 46
++#define RX_KER_BUF_REGION_WIDTH 2
++#define RX_KER_BUF_REGION0_DECODE 0
++#define RX_KER_BUF_REGION1_DECODE 1
++#define RX_KER_BUF_REGION2_DECODE 2
++#define RX_KER_BUF_REGION3_DECODE 3
++#define RX_KER_BUF_ADR_LBN 0
++#define RX_KER_BUF_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46)
++
++/**************************************************************************
++ *
++ * Falcon events
++ *
++ **************************************************************************
++ */
++
++/* Event queue entries */
++#define EV_CODE_LBN 60
++#define EV_CODE_WIDTH 4
++#define RX_IP_EV_DECODE 0
++#define TX_IP_EV_DECODE 2
++#define DRIVER_EV_DECODE 5
++#define GLOBAL_EV_DECODE 6
++#define DRV_GEN_EV_DECODE 7
++#define WHOLE_EVENT_LBN 0
++#define WHOLE_EVENT_WIDTH 64
++
++/* Receive events */
++#define RX_EV_PKT_OK_LBN 56
++#define RX_EV_PKT_OK_WIDTH 1
++#define RX_EV_PAUSE_FRM_ERR_LBN 55
++#define RX_EV_PAUSE_FRM_ERR_WIDTH 1
++#define RX_EV_BUF_OWNER_ID_ERR_LBN 54
++#define RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++#define RX_EV_IF_FRAG_ERR_LBN 53
++#define RX_EV_IF_FRAG_ERR_WIDTH 1
++#define RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
++#define RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
++#define RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
++#define RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
++#define RX_EV_ETH_CRC_ERR_LBN 50
++#define RX_EV_ETH_CRC_ERR_WIDTH 1
++#define RX_EV_FRM_TRUNC_LBN 49
++#define RX_EV_FRM_TRUNC_WIDTH 1
++#define RX_EV_DRIB_NIB_LBN 48
++#define RX_EV_DRIB_NIB_WIDTH 1
++#define RX_EV_TOBE_DISC_LBN 47
++#define RX_EV_TOBE_DISC_WIDTH 1
++#define RX_EV_PKT_TYPE_LBN 44
++#define RX_EV_PKT_TYPE_WIDTH 3
++#define RX_EV_PKT_TYPE_ETH_DECODE 0
++#define RX_EV_PKT_TYPE_LLC_DECODE 1
++#define RX_EV_PKT_TYPE_JUMBO_DECODE 2
++#define RX_EV_PKT_TYPE_VLAN_DECODE 3
++#define RX_EV_PKT_TYPE_VLAN_LLC_DECODE 4
++#define RX_EV_PKT_TYPE_VLAN_JUMBO_DECODE 5
++#define RX_EV_HDR_TYPE_LBN 42
++#define RX_EV_HDR_TYPE_WIDTH 2
++#define RX_EV_HDR_TYPE_TCP_IPV4_DECODE 0
++#define RX_EV_HDR_TYPE_UDP_IPV4_DECODE 1
++#define RX_EV_HDR_TYPE_OTHER_IP_DECODE 2
++#define RX_EV_HDR_TYPE_NON_IP_DECODE 3
++#define RX_EV_HDR_TYPE_HAS_CHECKSUMS(hdr_type) \
++ ((hdr_type) <= RX_EV_HDR_TYPE_UDP_IPV4_DECODE)
++#define RX_EV_DESC_Q_EMPTY_LBN 41
++#define RX_EV_DESC_Q_EMPTY_WIDTH 1
++#define RX_EV_MCAST_HASH_MATCH_LBN 40
++#define RX_EV_MCAST_HASH_MATCH_WIDTH 1
++#define RX_EV_MCAST_PKT_LBN 39
++#define RX_EV_MCAST_PKT_WIDTH 1
++#define RX_EV_RECOVERY_FLAG_LBN 37
++#define RX_EV_RECOVERY_FLAG_WIDTH 1
++#define RX_EV_Q_LABEL_LBN 32
++#define RX_EV_Q_LABEL_WIDTH 5
++#define RX_EV_JUMBO_CONT_LBN 31
++#define RX_EV_JUMBO_CONT_WIDTH 1
++#define RX_EV_PORT_LBN 30
++#define RX_EV_PORT_WIDTH 1
++#define RX_EV_BYTE_CNT_LBN 16
++#define RX_EV_BYTE_CNT_WIDTH 14
++#define RX_EV_SOP_LBN 15
++#define RX_EV_SOP_WIDTH 1
++#define RX_ISCSI_DDIG_ERR_LBN 13
++#define RX_ISCSI_DDIG_ERR_WIDTH 1
++#define RX_ISCSI_HDIG_ERR_LBN 12
++#define RX_ISCSI_HDIG_ERR_WIDTH 1
++#define RX_EV_DESC_PTR_LBN 0
++#define RX_EV_DESC_PTR_WIDTH 12
++
++/* Transmit events */
++#define TX_EV_PKT_ERR_LBN 38
++#define TX_EV_PKT_ERR_WIDTH 1
++#define TX_EV_PKT_TOO_BIG_LBN 37
++#define TX_EV_PKT_TOO_BIG_WIDTH 1
++#define TX_EV_Q_LABEL_LBN 32
++#define TX_EV_Q_LABEL_WIDTH 5
++#define TX_EV_PORT_LBN 16
++#define TX_EV_PORT_WIDTH 1
++#define TX_EV_WQ_FF_FULL_LBN 15
++#define TX_EV_WQ_FF_FULL_WIDTH 1
++#define TX_EV_BUF_OWNER_ID_ERR_LBN 14
++#define TX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++#define TX_EV_COMP_LBN 12
++#define TX_EV_COMP_WIDTH 1
++#define TX_EV_DESC_PTR_LBN 0
++#define TX_EV_DESC_PTR_WIDTH 12
++
++/* Driver events */
++#define DRIVER_EV_SUB_CODE_LBN 56
++#define DRIVER_EV_SUB_CODE_WIDTH 4
++#define DRIVER_EV_SUB_DATA_LBN 0
++#define DRIVER_EV_SUB_DATA_WIDTH 14
++#define TX_DESCQ_FLS_DONE_EV_DECODE 0
++#define RX_DESCQ_FLS_DONE_EV_DECODE 1
++#define EVQ_INIT_DONE_EV_DECODE 2
++#define EVQ_NOT_EN_EV_DECODE 3
++#define RX_DESCQ_FLSFF_OVFL_EV_DECODE 4
++#define SRM_UPD_DONE_EV_DECODE 5
++#define WAKE_UP_EV_DECODE 6
++#define TX_PKT_NON_TCP_UDP_DECODE 9
++#define TIMER_EV_DECODE 10
++#define RX_RECOVERY_EV_DECODE 11
++#define RX_DSC_ERROR_EV_DECODE 14
++#define TX_DSC_ERROR_EV_DECODE 15
++#define DRIVER_EV_TX_DESCQ_ID_LBN 0
++#define DRIVER_EV_TX_DESCQ_ID_WIDTH 12
++#define DRIVER_EV_RX_FLUSH_FAIL_LBN 12
++#define DRIVER_EV_RX_FLUSH_FAIL_WIDTH 1
++#define DRIVER_EV_RX_DESCQ_ID_LBN 0
++#define DRIVER_EV_RX_DESCQ_ID_WIDTH 12
++#define DRIVER_EV_EVQ_ID_LBN 0
++#define DRIVER_EV_EVQ_ID_WIDTH 12
++#define DRIVER_EV_SRM_UPD_LBN 0
++#define DRIVER_EV_SRM_UPD_WIDTH 2
++#define SRM_CLR_EV_DECODE 0
++#define SRM_UPD_EV_DECODE 1
++#define SRM_ILLCLR_EV_DECODE 2
++
++/* Global events */
++#define RX_RECOVERY_B0_LBN 12
++#define RX_RECOVERY_B0_WIDTH 1
++#define XG_MNT_INTR_B0_LBN 11
++#define XG_MNT_INTR_B0_WIDTH 1
++
++#define RX_RECOVERY_A1_LBN 11
++#define RX_RECOVERY_A1_WIDTH 1
++
++#define XFP_PHY_INTR_LBN 10
++#define XFP_PHY_INTR_WIDTH 1
++#define XG_PHY_INTR_LBN 9
++#define XG_PHY_INTR_WIDTH 1
++#define G_PHY1_INTR_LBN 8
++#define G_PHY1_INTR_WIDTH 1
++#define G_PHY0_INTR_LBN 7
++#define G_PHY0_INTR_WIDTH 1
++
++/* Driver-generated test events */
++#define DRV_GEN_EV_CODE_LBN 60
++#define DRV_GEN_EV_CODE_WIDTH 4
++#define DRV_GEN_EV_DATA_LBN 0
++#define DRV_GEN_EV_DATA_WIDTH 60
++#define EVQ_MAGIC_LBN 0
++#define EVQ_MAGIC_WIDTH 32
++
++/**************************************************************************
++ *
++ * Falcon MAC stats
++ *
++ **************************************************************************
++ *
++ */
++
++#define GRxGoodOct_offset 0x0
++#define GRxGoodOct_WIDTH 48
++#define GRxBadOct_offset 0x8
++#define GRxBadOct_WIDTH 48
++#define GRxMissPkt_offset 0x10
++#define GRxMissPkt_WIDTH 32
++#define GRxFalseCRS_offset 0x14
++#define GRxFalseCRS_WIDTH 32
++#define GRxPausePkt_offset 0x18
++#define GRxPausePkt_WIDTH 32
++#define GRxBadPkt_offset 0x1C
++#define GRxBadPkt_WIDTH 32
++#define GRxUcastPkt_offset 0x20
++#define GRxUcastPkt_WIDTH 32
++#define GRxMcastPkt_offset 0x24
++#define GRxMcastPkt_WIDTH 32
++#define GRxBcastPkt_offset 0x28
++#define GRxBcastPkt_WIDTH 32
++#define GRxGoodLt64Pkt_offset 0x2C
++#define GRxGoodLt64Pkt_WIDTH 32
++#define GRxBadLt64Pkt_offset 0x30
++#define GRxBadLt64Pkt_WIDTH 32
++#define GRx64Pkt_offset 0x34
++#define GRx64Pkt_WIDTH 32
++#define GRx65to127Pkt_offset 0x38
++#define GRx65to127Pkt_WIDTH 32
++#define GRx128to255Pkt_offset 0x3C
++#define GRx128to255Pkt_WIDTH 32
++#define GRx256to511Pkt_offset 0x40
++#define GRx256to511Pkt_WIDTH 32
++#define GRx512to1023Pkt_offset 0x44
++#define GRx512to1023Pkt_WIDTH 32
++#define GRx1024to15xxPkt_offset 0x48
++#define GRx1024to15xxPkt_WIDTH 32
++#define GRx15xxtoJumboPkt_offset 0x4C
++#define GRx15xxtoJumboPkt_WIDTH 32
++#define GRxGtJumboPkt_offset 0x50
++#define GRxGtJumboPkt_WIDTH 32
++#define GRxFcsErr64to15xxPkt_offset 0x54
++#define GRxFcsErr64to15xxPkt_WIDTH 32
++#define GRxFcsErr15xxtoJumboPkt_offset 0x58
++#define GRxFcsErr15xxtoJumboPkt_WIDTH 32
++#define GRxFcsErrGtJumboPkt_offset 0x5C
++#define GRxFcsErrGtJumboPkt_WIDTH 32
++#define GTxGoodBadOct_offset 0x80
++#define GTxGoodBadOct_WIDTH 48
++#define GTxGoodOct_offset 0x88
++#define GTxGoodOct_WIDTH 48
++#define GTxSglColPkt_offset 0x90
++#define GTxSglColPkt_WIDTH 32
++#define GTxMultColPkt_offset 0x94
++#define GTxMultColPkt_WIDTH 32
++#define GTxExColPkt_offset 0x98
++#define GTxExColPkt_WIDTH 32
++#define GTxDefPkt_offset 0x9C
++#define GTxDefPkt_WIDTH 32
++#define GTxLateCol_offset 0xA0
++#define GTxLateCol_WIDTH 32
++#define GTxExDefPkt_offset 0xA4
++#define GTxExDefPkt_WIDTH 32
++#define GTxPausePkt_offset 0xA8
++#define GTxPausePkt_WIDTH 32
++#define GTxBadPkt_offset 0xAC
++#define GTxBadPkt_WIDTH 32
++#define GTxUcastPkt_offset 0xB0
++#define GTxUcastPkt_WIDTH 32
++#define GTxMcastPkt_offset 0xB4
++#define GTxMcastPkt_WIDTH 32
++#define GTxBcastPkt_offset 0xB8
++#define GTxBcastPkt_WIDTH 32
++#define GTxLt64Pkt_offset 0xBC
++#define GTxLt64Pkt_WIDTH 32
++#define GTx64Pkt_offset 0xC0
++#define GTx64Pkt_WIDTH 32
++#define GTx65to127Pkt_offset 0xC4
++#define GTx65to127Pkt_WIDTH 32
++#define GTx128to255Pkt_offset 0xC8
++#define GTx128to255Pkt_WIDTH 32
++#define GTx256to511Pkt_offset 0xCC
++#define GTx256to511Pkt_WIDTH 32
++#define GTx512to1023Pkt_offset 0xD0
++#define GTx512to1023Pkt_WIDTH 32
++#define GTx1024to15xxPkt_offset 0xD4
++#define GTx1024to15xxPkt_WIDTH 32
++#define GTx15xxtoJumboPkt_offset 0xD8
++#define GTx15xxtoJumboPkt_WIDTH 32
++#define GTxGtJumboPkt_offset 0xDC
++#define GTxGtJumboPkt_WIDTH 32
++#define GTxNonTcpUdpPkt_offset 0xE0
++#define GTxNonTcpUdpPkt_WIDTH 16
++#define GTxMacSrcErrPkt_offset 0xE4
++#define GTxMacSrcErrPkt_WIDTH 16
++#define GTxIpSrcErrPkt_offset 0xE8
++#define GTxIpSrcErrPkt_WIDTH 16
++#define GDmaDone_offset 0xEC
++#define GDmaDone_WIDTH 32
++
++#define XgRxOctets_offset 0x0
++#define XgRxOctets_WIDTH 48
++#define XgRxOctetsOK_offset 0x8
++#define XgRxOctetsOK_WIDTH 48
++#define XgRxPkts_offset 0x10
++#define XgRxPkts_WIDTH 32
++#define XgRxPktsOK_offset 0x14
++#define XgRxPktsOK_WIDTH 32
++#define XgRxBroadcastPkts_offset 0x18
++#define XgRxBroadcastPkts_WIDTH 32
++#define XgRxMulticastPkts_offset 0x1C
++#define XgRxMulticastPkts_WIDTH 32
++#define XgRxUnicastPkts_offset 0x20
++#define XgRxUnicastPkts_WIDTH 32
++#define XgRxUndersizePkts_offset 0x24
++#define XgRxUndersizePkts_WIDTH 32
++#define XgRxOversizePkts_offset 0x28
++#define XgRxOversizePkts_WIDTH 32
++#define XgRxJabberPkts_offset 0x2C
++#define XgRxJabberPkts_WIDTH 32
++#define XgRxUndersizeFCSerrorPkts_offset 0x30
++#define XgRxUndersizeFCSerrorPkts_WIDTH 32
++#define XgRxDropEvents_offset 0x34
++#define XgRxDropEvents_WIDTH 32
++#define XgRxFCSerrorPkts_offset 0x38
++#define XgRxFCSerrorPkts_WIDTH 32
++#define XgRxAlignError_offset 0x3C
++#define XgRxAlignError_WIDTH 32
++#define XgRxSymbolError_offset 0x40
++#define XgRxSymbolError_WIDTH 32
++#define XgRxInternalMACError_offset 0x44
++#define XgRxInternalMACError_WIDTH 32
++#define XgRxControlPkts_offset 0x48
++#define XgRxControlPkts_WIDTH 32
++#define XgRxPausePkts_offset 0x4C
++#define XgRxPausePkts_WIDTH 32
++#define XgRxPkts64Octets_offset 0x50
++#define XgRxPkts64Octets_WIDTH 32
++#define XgRxPkts65to127Octets_offset 0x54
++#define XgRxPkts65to127Octets_WIDTH 32
++#define XgRxPkts128to255Octets_offset 0x58
++#define XgRxPkts128to255Octets_WIDTH 32
++#define XgRxPkts256to511Octets_offset 0x5C
++#define XgRxPkts256to511Octets_WIDTH 32
++#define XgRxPkts512to1023Octets_offset 0x60
++#define XgRxPkts512to1023Octets_WIDTH 32
++#define XgRxPkts1024to15xxOctets_offset 0x64
++#define XgRxPkts1024to15xxOctets_WIDTH 32
++#define XgRxPkts15xxtoMaxOctets_offset 0x68
++#define XgRxPkts15xxtoMaxOctets_WIDTH 32
++#define XgRxLengthError_offset 0x6C
++#define XgRxLengthError_WIDTH 32
++#define XgTxPkts_offset 0x80
++#define XgTxPkts_WIDTH 32
++#define XgTxOctets_offset 0x88
++#define XgTxOctets_WIDTH 48
++#define XgTxMulticastPkts_offset 0x90
++#define XgTxMulticastPkts_WIDTH 32
++#define XgTxBroadcastPkts_offset 0x94
++#define XgTxBroadcastPkts_WIDTH 32
++#define XgTxUnicastPkts_offset 0x98
++#define XgTxUnicastPkts_WIDTH 32
++#define XgTxControlPkts_offset 0x9C
++#define XgTxControlPkts_WIDTH 32
++#define XgTxPausePkts_offset 0xA0
++#define XgTxPausePkts_WIDTH 32
++#define XgTxPkts64Octets_offset 0xA4
++#define XgTxPkts64Octets_WIDTH 32
++#define XgTxPkts65to127Octets_offset 0xA8
++#define XgTxPkts65to127Octets_WIDTH 32
++#define XgTxPkts128to255Octets_offset 0xAC
++#define XgTxPkts128to255Octets_WIDTH 32
++#define XgTxPkts256to511Octets_offset 0xB0
++#define XgTxPkts256to511Octets_WIDTH 32
++#define XgTxPkts512to1023Octets_offset 0xB4
++#define XgTxPkts512to1023Octets_WIDTH 32
++#define XgTxPkts1024to15xxOctets_offset 0xB8
++#define XgTxPkts1024to15xxOctets_WIDTH 32
++#define XgTxPkts1519toMaxOctets_offset 0xBC
++#define XgTxPkts1519toMaxOctets_WIDTH 32
++#define XgTxUndersizePkts_offset 0xC0
++#define XgTxUndersizePkts_WIDTH 32
++#define XgTxOversizePkts_offset 0xC4
++#define XgTxOversizePkts_WIDTH 32
++#define XgTxNonTcpUdpPkt_offset 0xC8
++#define XgTxNonTcpUdpPkt_WIDTH 16
++#define XgTxMacSrcErrPkt_offset 0xCC
++#define XgTxMacSrcErrPkt_WIDTH 16
++#define XgTxIpSrcErrPkt_offset 0xD0
++#define XgTxIpSrcErrPkt_WIDTH 16
++#define XgDmaDone_offset 0xD4
++#define XgDmaDone_WIDTH 32
++
++#define FALCON_STATS_NOT_DONE 0x00000000
++#define FALCON_STATS_DONE 0xffffffff
++
++/* Interrupt status register bits */
++#define FATAL_INT_LBN 64
++#define FATAL_INT_WIDTH 1
++#define INT_EVQS_LBN 40
++#define INT_EVQS_WIDTH 4
++#define INT_FLAG_LBN 32
++#define INT_FLAG_WIDTH 1
++#define EVQ_FIFO_HF_LBN 1
++#define EVQ_FIFO_HF_WIDTH 1
++#define EVQ_FIFO_AF_LBN 0
++#define EVQ_FIFO_AF_WIDTH 1
++
++/**************************************************************************
++ *
++ * Falcon non-volatile configuration
++ *
++ **************************************************************************
++ */
++
++/* Board configuration v2 (v1 is obsolete; later versions are compatible) */
++struct falcon_nvconfig_board_v2 {
++ __le16 nports;
++ u8 port0_phy_addr;
++ u8 port0_phy_type;
++ u8 port1_phy_addr;
++ u8 port1_phy_type;
++ __le16 asic_sub_revision;
++ __le16 board_revision;
++} __attribute__ ((packed));
++
++/* Board configuration v3 extra information */
++struct falcon_nvconfig_board_v3 {
++ __le32 spi_device_type[2];
++} __attribute__ ((packed));
++
++/* Bit numbers for spi_device_type */
++#define SPI_DEV_TYPE_SIZE_LBN 0
++#define SPI_DEV_TYPE_SIZE_WIDTH 5
++#define SPI_DEV_TYPE_ADDR_LEN_LBN 6
++#define SPI_DEV_TYPE_ADDR_LEN_WIDTH 2
++#define SPI_DEV_TYPE_ERASE_CMD_LBN 8
++#define SPI_DEV_TYPE_ERASE_CMD_WIDTH 8
++#define SPI_DEV_TYPE_ERASE_SIZE_LBN 16
++#define SPI_DEV_TYPE_ERASE_SIZE_WIDTH 5
++#define SPI_DEV_TYPE_BLOCK_SIZE_LBN 24
++#define SPI_DEV_TYPE_BLOCK_SIZE_WIDTH 5
++#define SPI_DEV_TYPE_FIELD(type, field) \
++ (((type) >> EFX_LOW_BIT(field)) & EFX_MASK32(field))
++
++#define NVCONFIG_BASE 0x300
++#define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C
++struct falcon_nvconfig {
++ efx_oword_t ee_vpd_cfg_reg; /* 0x300 */
++ u8 mac_address[2][8]; /* 0x310 */
++ efx_oword_t pcie_sd_ctl0123_reg; /* 0x320 */
++ efx_oword_t pcie_sd_ctl45_reg; /* 0x330 */
++ efx_oword_t pcie_pcs_ctl_stat_reg; /* 0x340 */
++ efx_oword_t hw_init_reg; /* 0x350 */
++ efx_oword_t nic_stat_reg; /* 0x360 */
++ efx_oword_t glb_ctl_reg; /* 0x370 */
++ efx_oword_t srm_cfg_reg; /* 0x380 */
++ efx_oword_t spare_reg; /* 0x390 */
++ __le16 board_magic_num; /* 0x3A0 */
++ __le16 board_struct_ver;
++ __le16 board_checksum;
++ struct falcon_nvconfig_board_v2 board_v2;
++ efx_oword_t ee_base_page_reg; /* 0x3B0 */
++ struct falcon_nvconfig_board_v3 board_v3; /* 0x3C0 */
++} __attribute__ ((packed));
++
++#endif /* EFX_FALCON_HWDEFS_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/falcon_io.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon_io.h
+--- linux-2.6.18.8/drivers/net/sfc/falcon_io.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon_io.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,259 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_FALCON_IO_H
++#define EFX_FALCON_IO_H
++
++#include "net_driver.h"
++#include "falcon.h"
++
++/**************************************************************************
++ *
++ * Falcon hardware access
++ *
++ **************************************************************************
++ *
++ * Notes on locking strategy:
++ *
++ * Most Falcon registers require 16-byte (or 8-byte, for SRAM
++ * registers) atomic writes which necessitates locking.
++ * Under normal operation few writes to the Falcon BAR are made and these
++ * registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and TX_DESC_UPD_REG) are special
++ * cased to allow 4-byte (hence lockless) accesses.
++ *
++ * It *is* safe to write to these 4-byte registers in the middle of an
++ * access to an 8-byte or 16-byte register. We therefore use a
++ * spinlock to protect accesses to the larger registers, but no locks
++ * for the 4-byte registers.
++ *
++ * A write barrier is needed to ensure that DW3 is written after DW0/1/2
++ * due to the way the 16byte registers are "collected" in the Falcon BIU
++ *
++ * We also lock when carrying out reads, to ensure consistency of the
++ * data (made possible since the BIU reads all 128 bits into a cache).
++ * Reads are very rare, so this isn't a significant performance
++ * impact. (Most data transferred from NIC to host is DMAed directly
++ * into host memory).
++ *
++ * I/O BAR access uses locks for both reads and writes (but is only provided
++ * for testing purposes).
++ */
++
++/* Special buffer descriptors (Falcon SRAM) */
++#define BUF_TBL_KER_A1 0x18000
++#define BUF_TBL_KER_B0 0x800000
++
++
++#if BITS_PER_LONG == 64
++#define FALCON_USE_QWORD_IO 1
++#endif
++
++#define _falcon_writeq(efx, value, reg) \
++ __raw_writeq((__force u64) (value), (efx)->membase + (reg))
++#define _falcon_writel(efx, value, reg) \
++ __raw_writel((__force u32) (value), (efx)->membase + (reg))
++#define _falcon_readq(efx, reg) \
++ ((__force __le64) __raw_readq((efx)->membase + (reg)))
++#define _falcon_readl(efx, reg) \
++ ((__force __le32) __raw_readl((efx)->membase + (reg)))
++
++/* Writes to a normal 16-byte Falcon register, locking as appropriate. */
++static inline void falcon_write(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg)
++{
++ unsigned long flags __attribute__ ((unused));
++
++ EFX_REGDUMP(efx, "writing register %x with " EFX_OWORD_FMT "\n", reg,
++ EFX_OWORD_VAL(*value));
++
++ spin_lock_irqsave(&efx->biu_lock, flags);
++#ifdef FALCON_USE_QWORD_IO
++ _falcon_writeq(efx, value->u64[0], reg + 0);
++ wmb();
++ _falcon_writeq(efx, value->u64[1], reg + 8);
++#else
++ _falcon_writel(efx, value->u32[0], reg + 0);
++ _falcon_writel(efx, value->u32[1], reg + 4);
++ _falcon_writel(efx, value->u32[2], reg + 8);
++ wmb();
++ _falcon_writel(efx, value->u32[3], reg + 12);
++#endif
++ mmiowb();
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++}
++
++/* Writes to an 8-byte Falcon SRAM register, locking as appropriate. */
++static inline void falcon_write_sram(struct efx_nic *efx, efx_qword_t *value,
++ unsigned int index)
++{
++ unsigned int reg = efx->type->buf_tbl_base + (index * sizeof(*value));
++ unsigned long flags __attribute__ ((unused));
++
++ EFX_REGDUMP(efx, "writing SRAM register %x with " EFX_QWORD_FMT "\n",
++ reg, EFX_QWORD_VAL(*value));
++
++ spin_lock_irqsave(&efx->biu_lock, flags);
++#ifdef FALCON_USE_QWORD_IO
++ _falcon_writeq(efx, value->u64[0], reg + 0);
++#else
++ _falcon_writel(efx, value->u32[0], reg + 0);
++ wmb();
++ _falcon_writel(efx, value->u32[1], reg + 4);
++#endif
++ mmiowb();
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++}
++
++/* Write dword to Falcon register that allows partial writes
++ *
++ * Some Falcon registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and
++ * TX_DESC_UPD_REG) can be written to as a single dword. This allows
++ * for lockless writes.
++ */
++static inline void falcon_writel(struct efx_nic *efx, efx_dword_t *value,
++ unsigned int reg)
++{
++ EFX_REGDUMP(efx, "writing partial register %x with "EFX_DWORD_FMT"\n",
++ reg, EFX_DWORD_VAL(*value));
++
++ /* No lock required */
++ _falcon_writel(efx, value->u32[0], reg);
++}
++
++/* Read from a Falcon register
++ *
++ * This reads an entire 16-byte Falcon register in one go, locking as
++ * appropriate. It is essential to read the first dword first, as this
++ * prompts Falcon to load the current value into the shadow register.
++ */
++static inline void falcon_read(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg)
++{
++ unsigned long flags __attribute__ ((unused));
++
++ spin_lock_irqsave(&efx->biu_lock, flags);
++ value->u32[0] = _falcon_readl(efx, reg + 0);
++ rmb();
++ value->u32[1] = _falcon_readl(efx, reg + 4);
++ value->u32[2] = _falcon_readl(efx, reg + 8);
++ value->u32[3] = _falcon_readl(efx, reg + 12);
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++
++ EFX_REGDUMP(efx, "read from register %x, got " EFX_OWORD_FMT "\n", reg,
++ EFX_OWORD_VAL(*value));
++}
++
++/* This reads an 8-byte Falcon SRAM entry in one go. */
++static inline void falcon_read_sram(struct efx_nic *efx, efx_qword_t *value,
++ unsigned int index)
++{
++ unsigned int reg = efx->type->buf_tbl_base + (index * sizeof(*value));
++ unsigned long flags __attribute__ ((unused));
++
++ spin_lock_irqsave(&efx->biu_lock, flags);
++#ifdef FALCON_USE_QWORD_IO
++ value->u64[0] = _falcon_readq(efx, reg + 0);
++#else
++ value->u32[0] = _falcon_readl(efx, reg + 0);
++ rmb();
++ value->u32[1] = _falcon_readl(efx, reg + 4);
++#endif
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++
++ EFX_REGDUMP(efx, "read from SRAM register %x, got "EFX_QWORD_FMT"\n",
++ reg, EFX_QWORD_VAL(*value));
++}
++
++/* Read dword from Falcon register that allows partial writes (sic) */
++static inline void falcon_readl(struct efx_nic *efx, efx_dword_t *value,
++ unsigned int reg)
++{
++ value->u32[0] = _falcon_readl(efx, reg);
++ EFX_REGDUMP(efx, "read from register %x, got "EFX_DWORD_FMT"\n",
++ reg, EFX_DWORD_VAL(*value));
++}
++
++/* Write to a register forming part of a table */
++static inline void falcon_write_table(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg, unsigned int index)
++{
++ falcon_write(efx, value, reg + index * sizeof(efx_oword_t));
++}
++
++/* Read to a register forming part of a table */
++static inline void falcon_read_table(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg, unsigned int index)
++{
++ falcon_read(efx, value, reg + index * sizeof(efx_oword_t));
++}
++
++/* Write to a dword register forming part of a table */
++static inline void falcon_writel_table(struct efx_nic *efx, efx_dword_t *value,
++ unsigned int reg, unsigned int index)
++{
++ falcon_writel(efx, value, reg + index * sizeof(efx_oword_t));
++}
++
++/* Page-mapped register block size */
++#define FALCON_PAGE_BLOCK_SIZE 0x2000
++
++/* Calculate offset to page-mapped register block */
++#define FALCON_PAGED_REG(page, reg) \
++ ((page) * FALCON_PAGE_BLOCK_SIZE + (reg))
++
++/* As for falcon_write(), but for a page-mapped register. */
++static inline void falcon_write_page(struct efx_nic *efx, efx_oword_t *value,
++ unsigned int reg, unsigned int page)
++{
++ falcon_write(efx, value, FALCON_PAGED_REG(page, reg));
++}
++
++/* As for falcon_writel(), but for a page-mapped register. */
++static inline void falcon_writel_page(struct efx_nic *efx, efx_dword_t *value,
++ unsigned int reg, unsigned int page)
++{
++ falcon_writel(efx, value, FALCON_PAGED_REG(page, reg));
++}
++
++/* Write dword to Falcon page-mapped register with an extra lock.
++ *
++ * As for falcon_writel_page(), but for a register that suffers from
++ * SFC bug 3181. Take out a lock so the BIU collector cannot be
++ * confused. */
++static inline void falcon_writel_page_locked(struct efx_nic *efx,
++ efx_dword_t *value,
++ unsigned int reg,
++ unsigned int page)
++{
++ unsigned long flags __attribute__ ((unused));
++
++ spin_lock_irqsave(&efx->biu_lock, flags);
++ falcon_writel(efx, value, FALCON_PAGED_REG(page, reg));
++ spin_unlock_irqrestore(&efx->biu_lock, flags);
++}
++
++#endif /* EFX_FALCON_IO_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/falcon_xmac.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon_xmac.c
+--- linux-2.6.18.8/drivers/net/sfc/falcon_xmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/falcon_xmac.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,691 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/delay.h>
++#include "net_driver.h"
++#include "efx.h"
++#include "falcon.h"
++#include "falcon_hwdefs.h"
++#include "falcon_io.h"
++#include "mac.h"
++#include "gmii.h"
++#include "mdio_10g.h"
++#include "phy.h"
++#include "boards.h"
++#include "workarounds.h"
++
++/**************************************************************************
++ *
++ * MAC register access
++ *
++ **************************************************************************/
++
++/* Offset of an XMAC register within Falcon */
++#define FALCON_XMAC_REG(mac_reg) \
++ (FALCON_XMAC_REGBANK + ((mac_reg) * FALCON_XMAC_REG_SIZE))
++
++static void falcon_xmac_writel(struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg)
++{
++ efx_oword_t temp;
++
++ EFX_POPULATE_OWORD_1(temp, MAC_DATA, EFX_DWORD_FIELD(*value, MAC_DATA));
++ falcon_write(efx, &temp, FALCON_XMAC_REG(mac_reg));
++}
++
++static void falcon_xmac_readl(struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg)
++{
++ efx_oword_t temp;
++
++ falcon_read(efx, &temp, FALCON_XMAC_REG(mac_reg));
++ EFX_POPULATE_DWORD_1(*value, MAC_DATA, EFX_OWORD_FIELD(temp, MAC_DATA));
++}
++
++/**************************************************************************
++ *
++ * MAC operations
++ *
++ *************************************************************************/
++static int falcon_reset_xmac(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++ int count;
++
++ EFX_POPULATE_DWORD_1(reg, XM_CORE_RST, 1);
++ efx->mac_op->mac_writel(efx, &reg, XM_GLB_CFG_REG_MAC);
++
++ for (count = 0; count < 10000; count++) { /* wait upto 100ms */
++ efx->mac_op->mac_readl(efx, &reg, XM_GLB_CFG_REG_MAC);
++ if (EFX_DWORD_FIELD(reg, XM_CORE_RST) == 0)
++ return 0;
++ udelay(10);
++ }
++
++ EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
++ return -ETIMEDOUT;
++}
++
++/* Configure the XAUI driver that is an output from Falcon */
++static void falcon_setup_xaui(struct efx_nic *efx)
++{
++ efx_dword_t sdctl, txdrv;
++
++ /* Move the XAUI into low power, unless there is no PHY, in
++ * which case the XAUI will have to drive a cable. */
++ if (efx->phy_type == PHY_TYPE_NONE)
++ return;
++
++ efx->mac_op->mac_readl(efx, &sdctl, XX_SD_CTL_REG_MAC);
++ EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVD, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_LODRVD, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVC, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_LODRVC, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVB, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_LODRVB, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVA, XX_SD_CTL_DRV_DEFAULT);
++ EFX_SET_DWORD_FIELD(sdctl, XX_LODRVA, XX_SD_CTL_DRV_DEFAULT);
++ efx->mac_op->mac_writel(efx, &sdctl, XX_SD_CTL_REG_MAC);
++
++ EFX_POPULATE_DWORD_8(txdrv,
++ XX_DEQD, XX_TXDRV_DEQ_DEFAULT,
++ XX_DEQC, XX_TXDRV_DEQ_DEFAULT,
++ XX_DEQB, XX_TXDRV_DEQ_DEFAULT,
++ XX_DEQA, XX_TXDRV_DEQ_DEFAULT,
++ XX_DTXD, XX_TXDRV_DTX_DEFAULT,
++ XX_DTXC, XX_TXDRV_DTX_DEFAULT,
++ XX_DTXB, XX_TXDRV_DTX_DEFAULT,
++ XX_DTXA, XX_TXDRV_DTX_DEFAULT);
++ efx->mac_op->mac_writel(efx, &txdrv, XX_TXDRV_CTL_REG_MAC);
++}
++
++static void falcon_hold_xaui_in_rst(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++
++ EFX_ZERO_DWORD(reg);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNA_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNB_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNC_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDND_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTPLLAB_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTPLLCD_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETA_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETB_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETC_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETD_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++}
++
++static int _falcon_reset_xaui_a(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++
++ if (!efx->is_asic)
++ return 0;
++
++ falcon_hold_xaui_in_rst(efx);
++ efx->mac_op->mac_readl(efx, &reg, XX_PWR_RST_REG_MAC);
++
++ /* Follow the RAMBUS XAUI data reset sequencing
++ * Channels A and B first: power down, reset PLL, reset, clear
++ */
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNA_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNB_EN, 0);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ EFX_SET_DWORD_FIELD(reg, XX_RSTPLLAB_EN, 0);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ EFX_SET_DWORD_FIELD(reg, XX_RESETA_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETB_EN, 0);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ /* Channels C and D: power down, reset PLL, reset, clear */
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDNC_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_PWRDND_EN, 0);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ EFX_SET_DWORD_FIELD(reg, XX_RSTPLLCD_EN, 0);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ EFX_SET_DWORD_FIELD(reg, XX_RESETC_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_RESETD_EN, 0);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ /* Setup XAUI */
++ falcon_setup_xaui(efx);
++ udelay(10);
++
++ /* Take XGXS out of reset */
++ EFX_ZERO_DWORD(reg);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ return 0;
++}
++
++static int _falcon_reset_xaui_b(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++ int count;
++
++ if (!efx->is_asic)
++ return 0;
++
++ EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++
++ /* Give some time for the link to establish */
++ for (count = 0; count < 1000; count++) { /* wait upto 10ms */
++ efx->mac_op->mac_readl(efx, &reg, XX_PWR_RST_REG_MAC);
++ if (EFX_DWORD_FIELD(reg, XX_RST_XX_EN) == 0) {
++ falcon_setup_xaui(efx);
++ return 0;
++ }
++ udelay(10);
++ }
++ EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n");
++ return -ETIMEDOUT;
++}
++
++int falcon_reset_xaui(struct efx_nic *efx)
++{
++ int rc;
++
++ if (EFX_WORKAROUND_9388(efx)) {
++ falcon_hold_xaui_in_rst(efx);
++ efx->phy_op->reset_xaui(efx);
++ rc = _falcon_reset_xaui_a(efx);
++ } else {
++ rc = _falcon_reset_xaui_b(efx);
++ }
++ return rc;
++}
++
++static int falcon_init_xmac(struct efx_nic *efx)
++{
++ int rc;
++
++ /* Initialize the PHY first so the clock is around */
++ rc = efx->phy_op->init(efx);
++ if (rc)
++ goto fail1;
++
++ rc = falcon_reset_xaui(efx);
++ if (rc)
++ goto fail2;
++
++ /* Wait again. Give the PHY and MAC time to faff */
++ schedule_timeout_uninterruptible(HZ / 10);
++
++ /* Reset the MAC */
++ rc = falcon_reset_xmac(efx);
++ if (rc)
++ goto fail2;
++
++ return 0;
++
++ fail2:
++ efx->phy_op->fini(efx);
++ fail1:
++ return rc;
++}
++
++/* Get status of XAUI link */
++int falcon_xaui_link_ok(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++ int align_done;
++ int sync_status;
++ int link_ok = 0;
++
++ /* If we're in internal loopback, then the link is up.
++ * The A1 FPGA/4G has RX and TX XAUI wired together, so the link is up.
++ * The B0 FPGA has XAUI offchip, so it is always up.
++ */
++ if (!efx->is_asic || LOOPBACK_INTERNAL(efx))
++ return 1;
++
++ /* Read link status */
++ efx->mac_op->mac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
++
++ align_done = EFX_DWORD_FIELD(reg, XX_ALIGN_DONE);
++ sync_status = EFX_DWORD_FIELD(reg, XX_SYNC_STAT);
++ if (align_done && (sync_status == XX_SYNC_STAT_DECODE_SYNCED))
++ link_ok = 1;
++
++ /* Clear link status ready for next read */
++ EFX_SET_DWORD_FIELD(reg, XX_COMMA_DET, XX_COMMA_DET_RESET);
++ EFX_SET_DWORD_FIELD(reg, XX_CHARERR, XX_CHARERR_RESET);
++ EFX_SET_DWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET);
++
++ efx->mac_op->mac_writel(efx, &reg, XX_CORE_STAT_REG_MAC);
++
++ return link_ok;
++}
++
++/* Do most of the heavy lifting of falcon_reconfigure_xmac */
++static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
++{
++ unsigned int max_frame_len;
++ efx_dword_t reg;
++ efx_oword_t mac_test_reg;
++ int rx_fc = (efx->flow_control & EFX_FC_RX) ? 1 : 0;
++
++ if (FALCON_REV(efx) <= FALCON_REV_A1 && !efx->is_asic) {
++ /* 10G FPGA's have the XAUI TX and RX wired together. Fake
++ * the link status and configure the link options before
++ * the MAC wrapper is configured */
++ efx->link_options = GM_LPA_10000FULL;
++ efx->link_up = 1;
++ }
++
++ /* Configure MAC - cut-thru mode is hard wired on */
++ EFX_POPULATE_DWORD_3(reg,
++ XM_RX_JUMBO_MODE, 1,
++ XM_TX_STAT_EN, 1,
++ XM_RX_STAT_EN, 1);
++ efx->mac_op->mac_writel(efx, &reg, XM_GLB_CFG_REG_MAC);
++
++ /* Configure TX */
++ EFX_POPULATE_DWORD_6(reg,
++ XM_TXEN, 1,
++ XM_TX_PRMBL, 1,
++ XM_AUTO_PAD, 1,
++ XM_TXCRC, 1,
++ XM_FCNTL, 1,
++ XM_IPG, 0x3);
++ efx->mac_op->mac_writel(efx, &reg, XM_TX_CFG_REG_MAC);
++
++ /* Configure RX */
++ EFX_POPULATE_DWORD_5(reg,
++ XM_RXEN, 1,
++ XM_AUTO_DEPAD, 0,
++ XM_ACPT_ALL_MCAST, 1,
++ XM_ACPT_ALL_UCAST, efx->promiscuous,
++ XM_PASS_CRC_ERR, 1);
++ efx->mac_op->mac_writel(efx, &reg, XM_RX_CFG_REG_MAC);
++
++ /* Set frame length */
++ max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
++ EFX_POPULATE_DWORD_1(reg, XM_MAX_RX_FRM_SIZE, max_frame_len);
++ efx->mac_op->mac_writel(efx, &reg, XM_RX_PARAM_REG_MAC);
++ EFX_POPULATE_DWORD_2(reg,
++ XM_MAX_TX_FRM_SIZE, max_frame_len,
++ XM_TX_JUMBO_MODE, 1);
++ efx->mac_op->mac_writel(efx, &reg, XM_TX_PARAM_REG_MAC);
++
++ EFX_POPULATE_DWORD_2(reg,
++ XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */
++ XM_DIS_FCNTL, rx_fc ? 0 : 1);
++ efx->mac_op->mac_writel(efx, &reg, XM_FC_REG_MAC);
++
++ /* Set MAC address */
++ EFX_POPULATE_DWORD_4(reg,
++ XM_ADR_0, efx->net_dev->dev_addr[0],
++ XM_ADR_1, efx->net_dev->dev_addr[1],
++ XM_ADR_2, efx->net_dev->dev_addr[2],
++ XM_ADR_3, efx->net_dev->dev_addr[3]);
++ efx->mac_op->mac_writel(efx, &reg, XM_ADR_LO_REG_MAC);
++ EFX_POPULATE_DWORD_2(reg,
++ XM_ADR_4, efx->net_dev->dev_addr[4],
++ XM_ADR_5, efx->net_dev->dev_addr[5]);
++ efx->mac_op->mac_writel(efx, &reg, XM_ADR_HI_REG_MAC);
++
++ /* Handle B0 FPGA loopback where RAMBUS XGXS block not present */
++ if (FALCON_REV(efx) == FALCON_REV_B0 && !efx->is_asic) {
++ int xgmii_loopback =
++ (efx->loopback_mode == LOOPBACK_XGMII) ? 1 : 0;
++
++ /* Set the MAC loopback bit. */
++ EFX_POPULATE_OWORD_1(mac_test_reg,
++ MAC_PTLOOP_EN, xgmii_loopback);
++ falcon_write(efx, &mac_test_reg, MAC_TEST_REG_KER);
++ }
++}
++
++/* Do most of the heavy lifting of falcon_reconfigure_xmac */
++static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++ int xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS) ? 1 : 0;
++ int xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI) ? 1 : 0;
++ int xgmii_loopback =
++ (efx->loopback_mode == LOOPBACK_XGMII) ? 1 : 0;
++
++ if (FALCON_REV(efx) == FALCON_REV_B0 && !efx->is_asic)
++ /* RAMBUS XGXS block is not present */
++ return;
++
++ /* XGXS block is flaky and will need to be reset if moving
++ * into our out of XGMII, XGXS or XAUI loopbacks. */
++ if (EFX_WORKAROUND_5147(efx)) {
++ int old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback;
++ int reset_xgxs;
++
++ efx->mac_op->mac_readl(efx, &reg,
++ XX_CORE_STAT_REG_MAC);
++ old_xgxs_loopback = EFX_DWORD_FIELD(reg, XX_XGXS_LB_EN);
++ old_xgmii_loopback = EFX_DWORD_FIELD(reg, XX_XGMII_LB_EN);
++
++ efx->mac_op->mac_readl(efx, &reg, XX_SD_CTL_REG_MAC);
++ old_xaui_loopback = EFX_DWORD_FIELD(reg, XX_LPBKA);
++
++ /* The PHY driver may have turned XAUI off */
++ reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) ||
++ (xaui_loopback != old_xaui_loopback) ||
++ (xgmii_loopback != old_xgmii_loopback));
++ if (reset_xgxs) {
++ efx->mac_op->mac_readl(efx, &reg,
++ XX_PWR_RST_REG_MAC);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1);
++ efx->mac_op->mac_writel(efx, &reg,
++ XX_PWR_RST_REG_MAC);
++ udelay(1);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 0);
++ EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 0);
++ efx->mac_op->mac_writel(efx, &reg,
++ XX_PWR_RST_REG_MAC);
++ udelay(1);
++ }
++ }
++
++ efx->mac_op->mac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
++ EFX_SET_DWORD_FIELD(reg, XX_FORCE_SIG,
++ (xgxs_loopback || xaui_loopback) ?
++ XX_FORCE_SIG_DECODE_FORCED : 0);
++ EFX_SET_DWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback);
++ EFX_SET_DWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback);
++ efx->mac_op->mac_writel(efx, &reg, XX_CORE_STAT_REG_MAC);
++
++ efx->mac_op->mac_readl(efx, &reg, XX_SD_CTL_REG_MAC);
++ EFX_SET_DWORD_FIELD(reg, XX_LPBKD, xaui_loopback);
++ EFX_SET_DWORD_FIELD(reg, XX_LPBKC, xaui_loopback);
++ EFX_SET_DWORD_FIELD(reg, XX_LPBKB, xaui_loopback);
++ EFX_SET_DWORD_FIELD(reg, XX_LPBKA, xaui_loopback);
++ efx->mac_op->mac_writel(efx, &reg, XX_SD_CTL_REG_MAC);
++}
++
++
++/* Sometimes the XAUI link between Falcon and XFP fails to come up. The state
++ * of the link is checked during phy_reconfigure(). After XAIU is reset then
++ * the MAC must be reconfigured.
++ */
++#define MAX_XAUI_TRIES (5) /* It's never been seen to take more than 2 */
++
++void falcon_check_xaui_link_up(struct efx_nic *efx)
++{
++ int max_tries, tries;
++ tries = EFX_WORKAROUND_5147(efx) ? MAX_XAUI_TRIES : 1;
++ max_tries = tries;
++
++ if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
++ (efx->phy_type == PHY_TYPE_NONE) ||
++ !efx->phy_powered)
++ return;
++
++ while (tries) {
++ if (falcon_xaui_link_ok(efx))
++ return;
++
++ EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n",
++ __func__, tries);
++ (void) falcon_reset_xaui(efx);
++ /* Cannot use full reconfigure. Need to avoid recursion */
++
++ /* Give the poor thing time to sort itself out: if we retry
++ * too fast it will never train. */
++ udelay(200);
++
++ falcon_reconfigure_xgxs_core(efx);
++
++ tries--;
++ }
++
++ EFX_ERR(efx, "Failed to bring XAUI link back up in %d tries!\n",
++ max_tries);
++}
++
++static void falcon_reconfigure_xmac(struct efx_nic *efx)
++{
++ falcon_deconfigure_mac_wrapper(efx);
++
++ /* In internal loopback modes disable transmit */
++ efx->tx_disabled = LOOPBACK_INTERNAL(efx);
++
++ efx->phy_op->reconfigure(efx);
++
++ falcon_reconfigure_xgxs_core(efx);
++ falcon_reconfigure_xmac_core(efx);
++
++ /* Reconfigure MAC wrapper */
++ falcon_reconfigure_mac_wrapper(efx);
++
++ /* Ensure XAUI link is up - might repeat reconfigure_xmac_core */
++ falcon_check_xaui_link_up(efx);
++}
++
++static void falcon_fini_xmac(struct efx_nic *efx)
++{
++ /* Isolate the MAC - PHY */
++ falcon_deconfigure_mac_wrapper(efx);
++
++ /* Potentially power down the PHY */
++ efx->phy_op->fini(efx);
++}
++
++static void falcon_update_stats_xmac(struct efx_nic *efx)
++{
++ struct efx_mac_stats *mac_stats = &efx->mac_stats;
++ int rc;
++
++ rc = falcon_dma_stats(efx, XgDmaDone_offset);
++ if (rc)
++ return;
++
++ /* Update MAC stats from DMAed values */
++ FALCON_STAT(efx, XgRxOctets, rx_bytes);
++ FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes);
++ FALCON_STAT(efx, XgRxPkts, rx_packets);
++ FALCON_STAT(efx, XgRxPktsOK, rx_good);
++ FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast);
++ FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast);
++ FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast);
++ FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64);
++ FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo);
++ FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo);
++ FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64);
++ FALCON_STAT(efx, XgRxDropEvents, rx_overflow);
++ FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad);
++ FALCON_STAT(efx, XgRxAlignError, rx_align_error);
++ FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error);
++ FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error);
++ FALCON_STAT(efx, XgRxControlPkts, rx_control);
++ FALCON_STAT(efx, XgRxPausePkts, rx_pause);
++ FALCON_STAT(efx, XgRxPkts64Octets, rx_64);
++ FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127);
++ FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255);
++ FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511);
++ FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023);
++ FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx);
++ FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo);
++ FALCON_STAT(efx, XgRxLengthError, rx_length_error);
++ FALCON_STAT(efx, XgTxPkts, tx_packets);
++ FALCON_STAT(efx, XgTxOctets, tx_bytes);
++ FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast);
++ FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast);
++ FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast);
++ FALCON_STAT(efx, XgTxControlPkts, tx_control);
++ FALCON_STAT(efx, XgTxPausePkts, tx_pause);
++ FALCON_STAT(efx, XgTxPkts64Octets, tx_64);
++ FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127);
++ FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255);
++ FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511);
++ FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023);
++ FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx);
++ FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo);
++ FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64);
++ FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo);
++ FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp);
++ FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error);
++ FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error);
++
++ /* Update derived statistics */
++ mac_stats->tx_good_bytes =
++ (mac_stats->tx_bytes - mac_stats->tx_bad_bytes);
++ mac_stats->rx_bad_bytes =
++ (mac_stats->rx_bytes - mac_stats->rx_good_bytes);
++}
++
++#define EFX_XAUI_RETRAIN_MAX 8
++
++static int falcon_check_xmac(struct efx_nic *efx)
++{
++ unsigned link_ok, phyxs_ok = 1;
++ unsigned has_phyxs = efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS);
++
++ /* Check the remote XAUI link status */
++ link_ok = falcon_xaui_link_ok(efx);
++
++ if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
++ !efx->phy_powered)
++ return 0;
++
++ if (link_ok && has_phyxs && !LOOPBACK_INTERNAL(efx)) {
++ /* Does the PHYXS think we have lane sync? */
++ phyxs_ok = mdio_clause45_phyxgxs_lane_sync(efx);
++ }
++
++ if (EFX_WORKAROUND_5147(efx) && (!link_ok || !phyxs_ok)) {
++ (void) falcon_reset_xaui(efx);
++ falcon_reconfigure_xgxs_core(efx);
++ }
++
++ /* Call the PHY check_hw routine */
++ efx->phy_op->check_hw(efx);
++ return 0;
++}
++
++/* Simulate a PHY event */
++static void falcon_xmac_sim_phy_event(struct efx_nic *efx)
++{
++ efx_qword_t phy_event;
++
++ EFX_POPULATE_QWORD_2(phy_event,
++ EV_CODE, GLOBAL_EV_DECODE,
++ XG_PHY_INTR, 1);
++ falcon_generate_event(&efx->channel[0], &phy_event);
++}
++
++static int falcon_xmac_get_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd)
++{
++ mdio_clause45_get_settings(efx, ecmd);
++ ecmd->transceiver = XCVR_INTERNAL;
++ ecmd->phy_address = efx->mii.phy_id;
++ ecmd->autoneg = AUTONEG_DISABLE;
++ ecmd->duplex = DUPLEX_FULL;
++ return 0;
++}
++
++static int falcon_xmac_set_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd)
++{
++ if (ecmd->transceiver != XCVR_INTERNAL)
++ return -EINVAL;
++ if (ecmd->autoneg != AUTONEG_DISABLE)
++ return -EINVAL;
++ if (ecmd->duplex != DUPLEX_FULL)
++ return -EINVAL;
++
++ return mdio_clause45_set_settings(efx, ecmd);
++}
++
++
++static int falcon_xmac_set_pause(struct efx_nic *efx,
++ enum efx_fc_type flow_control)
++{
++ int reset;
++
++ if (flow_control & EFX_FC_AUTO) {
++ EFX_LOG(efx, "10G does not support flow control "
++ "autonegotiation\n");
++ return -EINVAL;
++ }
++
++ if ((flow_control & EFX_FC_TX) && !(flow_control & EFX_FC_RX))
++ return -EINVAL;
++
++ /* TX flow control may automatically turn itself off if the
++ * link partner (intermittently) stops responding to pause
++ * frames. There isn't any indication that this has happened,
++ * so the best we do is leave it up to the user to spot this
++ * and fix it be cycling transmit flow control on this end. */
++ reset = ((flow_control & EFX_FC_TX) &&
++ !(efx->flow_control & EFX_FC_TX));
++ if (EFX_WORKAROUND_11482(efx) && reset) {
++ if (FALCON_REV(efx) == FALCON_REV_B0) {
++ /* Recover by resetting the EM block */
++ mutex_lock(&efx->mac_lock);
++ if (efx->link_up)
++ falcon_drain_tx_fifo(efx);
++ mutex_unlock(&efx->mac_lock);
++ } else {
++ /* Schedule a reset to recover */
++ efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
++ }
++ }
++
++ efx->flow_control = flow_control;
++
++ return 0;
++}
++
++struct efx_mac_operations falcon_xmac_operations = {
++ .mac_writel = falcon_xmac_writel,
++ .mac_readl = falcon_xmac_readl,
++ .init = falcon_init_xmac,
++ .reconfigure = falcon_reconfigure_xmac,
++ .update_stats = falcon_update_stats_xmac,
++ .fini = falcon_fini_xmac,
++ .check_hw = falcon_check_xmac,
++ .fake_phy_event = falcon_xmac_sim_phy_event,
++ .get_settings = falcon_xmac_get_settings,
++ .set_settings = falcon_xmac_set_settings,
++ .set_pause = falcon_xmac_set_pause,
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/gmii.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/gmii.h
+--- linux-2.6.18.8/drivers/net/sfc/gmii.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/gmii.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,212 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_GMII_H
++#define EFX_GMII_H
++
++/*
++ * GMII interface
++ */
++
++#include <linux/mii.h>
++
++/* GMII registers, excluding registers already defined as MII
++ * registers in mii.h
++ */
++#define GMII_IER 0x12 /* Interrupt enable register */
++#define GMII_ISR 0x13 /* Interrupt status register */
++
++/* Interrupt enable register */
++#define IER_ANEG_ERR 0x8000 /* Bit 15 - autonegotiation error */
++#define IER_SPEED_CHG 0x4000 /* Bit 14 - speed changed */
++#define IER_DUPLEX_CHG 0x2000 /* Bit 13 - duplex changed */
++#define IER_PAGE_RCVD 0x1000 /* Bit 12 - page received */
++#define IER_ANEG_DONE 0x0800 /* Bit 11 - autonegotiation complete */
++#define IER_LINK_CHG 0x0400 /* Bit 10 - link status changed */
++#define IER_SYM_ERR 0x0200 /* Bit 9 - symbol error */
++#define IER_FALSE_CARRIER 0x0100 /* Bit 8 - false carrier */
++#define IER_FIFO_ERR 0x0080 /* Bit 7 - FIFO over/underflow */
++#define IER_MDIX_CHG 0x0040 /* Bit 6 - MDI crossover changed */
++#define IER_DOWNSHIFT 0x0020 /* Bit 5 - downshift */
++#define IER_ENERGY 0x0010 /* Bit 4 - energy detect */
++#define IER_DTE_POWER 0x0004 /* Bit 2 - DTE power detect */
++#define IER_POLARITY_CHG 0x0002 /* Bit 1 - polarity changed */
++#define IER_JABBER 0x0001 /* Bit 0 - jabber */
++
++/* Interrupt status register */
++#define ISR_ANEG_ERR 0x8000 /* Bit 15 - autonegotiation error */
++#define ISR_SPEED_CHG 0x4000 /* Bit 14 - speed changed */
++#define ISR_DUPLEX_CHG 0x2000 /* Bit 13 - duplex changed */
++#define ISR_PAGE_RCVD 0x1000 /* Bit 12 - page received */
++#define ISR_ANEG_DONE 0x0800 /* Bit 11 - autonegotiation complete */
++#define ISR_LINK_CHG 0x0400 /* Bit 10 - link status changed */
++#define ISR_SYM_ERR 0x0200 /* Bit 9 - symbol error */
++#define ISR_FALSE_CARRIER 0x0100 /* Bit 8 - false carrier */
++#define ISR_FIFO_ERR 0x0080 /* Bit 7 - FIFO over/underflow */
++#define ISR_MDIX_CHG 0x0040 /* Bit 6 - MDI crossover changed */
++#define ISR_DOWNSHIFT 0x0020 /* Bit 5 - downshift */
++#define ISR_ENERGY 0x0010 /* Bit 4 - energy detect */
++#define ISR_DTE_POWER 0x0004 /* Bit 2 - DTE power detect */
++#define ISR_POLARITY_CHG 0x0002 /* Bit 1 - polarity changed */
++#define ISR_JABBER 0x0001 /* Bit 0 - jabber */
++
++/* Logically extended advertisement register */
++#define GM_ADVERTISE_SLCT ADVERTISE_SLCT
++#define GM_ADVERTISE_CSMA ADVERTISE_CSMA
++#define GM_ADVERTISE_10HALF ADVERTISE_10HALF
++#define GM_ADVERTISE_1000XFULL ADVERTISE_1000XFULL
++#define GM_ADVERTISE_10FULL ADVERTISE_10FULL
++#define GM_ADVERTISE_1000XHALF ADVERTISE_1000XHALF
++#define GM_ADVERTISE_100HALF ADVERTISE_100HALF
++#define GM_ADVERTISE_1000XPAUSE ADVERTISE_1000XPAUSE
++#define GM_ADVERTISE_100FULL ADVERTISE_100FULL
++#define GM_ADVERTISE_1000XPSE_ASYM ADVERTISE_1000XPSE_ASYM
++#define GM_ADVERTISE_100BASE4 ADVERTISE_100BASE4
++#define GM_ADVERTISE_PAUSE_CAP ADVERTISE_PAUSE_CAP
++#define GM_ADVERTISE_PAUSE_ASYM ADVERTISE_PAUSE_ASYM
++#define GM_ADVERTISE_RESV ADVERTISE_RESV
++#define GM_ADVERTISE_RFAULT ADVERTISE_RFAULT
++#define GM_ADVERTISE_LPACK ADVERTISE_LPACK
++#define GM_ADVERTISE_NPAGE ADVERTISE_NPAGE
++#define GM_ADVERTISE_1000FULL (ADVERTISE_1000FULL << 8)
++#define GM_ADVERTISE_1000HALF (ADVERTISE_1000HALF << 8)
++#define GM_ADVERTISE_1000 (GM_ADVERTISE_1000FULL | \
++ GM_ADVERTISE_1000HALF)
++#define GM_ADVERTISE_FULL (GM_ADVERTISE_1000FULL | \
++ ADVERTISE_FULL)
++#define GM_ADVERTISE_ALL (GM_ADVERTISE_1000FULL | \
++ GM_ADVERTISE_1000HALF | \
++ ADVERTISE_ALL)
++
++/* Logically extended link partner ability register */
++#define GM_LPA_SLCT LPA_SLCT
++#define GM_LPA_10HALF LPA_10HALF
++#define GM_LPA_1000XFULL LPA_1000XFULL
++#define GM_LPA_10FULL LPA_10FULL
++#define GM_LPA_1000XHALF LPA_1000XHALF
++#define GM_LPA_100HALF LPA_100HALF
++#define GM_LPA_1000XPAUSE LPA_1000XPAUSE
++#define GM_LPA_100FULL LPA_100FULL
++#define GM_LPA_1000XPAUSE_ASYM LPA_1000XPAUSE_ASYM
++#define GM_LPA_100BASE4 LPA_100BASE4
++#define GM_LPA_PAUSE_CAP LPA_PAUSE_CAP
++#define GM_LPA_PAUSE_ASYM LPA_PAUSE_ASYM
++#define GM_LPA_RESV LPA_RESV
++#define GM_LPA_RFAULT LPA_RFAULT
++#define GM_LPA_LPACK LPA_LPACK
++#define GM_LPA_NPAGE LPA_NPAGE
++#define GM_LPA_1000FULL (LPA_1000FULL << 6)
++#define GM_LPA_1000HALF (LPA_1000HALF << 6)
++#define GM_LPA_10000FULL 0x00040000
++#define GM_LPA_10000HALF 0x00080000
++#define GM_LPA_DUPLEX (GM_LPA_1000FULL | GM_LPA_10000FULL \
++ | LPA_DUPLEX)
++#define GM_LPA_10 (LPA_10FULL | LPA_10HALF)
++#define GM_LPA_100 LPA_100
++#define GM_LPA_1000 (GM_LPA_1000FULL | GM_LPA_1000HALF)
++#define GM_LPA_10000 (GM_LPA_10000FULL | GM_LPA_10000HALF)
++
++/* Retrieve GMII autonegotiation advertised abilities
++ *
++ * The MII advertisment register (MII_ADVERTISE) is logically extended
++ * to include advertisement bits ADVERTISE_1000FULL and
++ * ADVERTISE_1000HALF from MII_CTRL1000. The result can be tested
++ * against the GM_ADVERTISE_xxx constants.
++ */
++static inline unsigned int gmii_advertised(struct mii_if_info *gmii)
++{
++ unsigned int advertise;
++ unsigned int ctrl1000;
++
++ advertise = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_ADVERTISE);
++ ctrl1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_CTRL1000);
++ return (((ctrl1000 << 8) & GM_ADVERTISE_1000) | advertise);
++}
++
++/* Retrieve GMII autonegotiation link partner abilities
++ *
++ * The MII link partner ability register (MII_LPA) is logically
++ * extended by adding bits LPA_1000HALF and LPA_1000FULL from
++ * MII_STAT1000. The result can be tested against the GM_LPA_xxx
++ * constants.
++ */
++static inline unsigned int gmii_lpa(struct mii_if_info *gmii)
++{
++ unsigned int lpa;
++ unsigned int stat1000;
++
++ lpa = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_LPA);
++ stat1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_STAT1000);
++ return (((stat1000 << 6) & GM_LPA_1000) | lpa);
++}
++
++/* Calculate GMII autonegotiated link technology
++ *
++ * "negotiated" should be the result of gmii_advertised() logically
++ * ANDed with the result of gmii_lpa().
++ *
++ * "tech" will be negotiated with the unused bits masked out. For
++ * example, if both ends of the link are capable of both
++ * GM_LPA_1000FULL and GM_LPA_100FULL, GM_LPA_100FULL will be masked
++ * out.
++ */
++static inline unsigned int gmii_nway_result(unsigned int negotiated)
++{
++ unsigned int other_bits;
++
++ /* Mask out the speed and duplexity bits */
++ other_bits = negotiated & ~(GM_LPA_10 | GM_LPA_100 | GM_LPA_1000);
++
++ if (negotiated & GM_LPA_1000FULL)
++ return (other_bits | GM_LPA_1000FULL);
++ else if (negotiated & GM_LPA_1000HALF)
++ return (other_bits | GM_LPA_1000HALF);
++ else
++ return (other_bits | mii_nway_result(negotiated));
++}
++
++/* Calculate GMII non-autonegotiated link technology
++ *
++ * This provides an equivalent to gmii_nway_result for the case when
++ * autonegotiation is disabled.
++ */
++static inline unsigned int gmii_forced_result(unsigned int bmcr)
++{
++ unsigned int result;
++ int full_duplex;
++
++ full_duplex = bmcr & BMCR_FULLDPLX;
++ if (bmcr & BMCR_SPEED1000)
++ result = full_duplex ? GM_LPA_1000FULL : GM_LPA_1000HALF;
++ else if (bmcr & BMCR_SPEED100)
++ result = full_duplex ? GM_LPA_100FULL : GM_LPA_100HALF;
++ else
++ result = full_duplex ? GM_LPA_10FULL : GM_LPA_10HALF;
++ return result;
++}
++
++#endif /* EFX_GMII_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/i2c-direct.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/i2c-direct.c
+--- linux-2.6.18.8/drivers/net/sfc/i2c-direct.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/i2c-direct.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,398 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <asm/io.h>
++#include <linux/delay.h>
++#include "net_driver.h"
++#include "i2c-direct.h"
++
++/* EEPROM access via I2C
++ * data (SDA) and clock (SCL) line read/writes
++ */
++
++static inline void setsda(struct efx_i2c_interface *i2c, int state)
++{
++ udelay(i2c->op->udelay);
++ i2c->sda = state;
++ i2c->op->setsda(i2c);
++ udelay(i2c->op->udelay);
++}
++
++static inline void setscl(struct efx_i2c_interface *i2c, int state)
++{
++ udelay(i2c->op->udelay);
++ i2c->scl = state;
++ i2c->op->setscl(i2c);
++ udelay(i2c->op->udelay);
++}
++
++static inline int getsda(struct efx_i2c_interface *i2c)
++{
++ int sda;
++
++ udelay(i2c->op->udelay);
++ sda = i2c->op->getsda(i2c);
++ udelay(i2c->op->udelay);
++ return sda;
++}
++
++static inline int getscl(struct efx_i2c_interface *i2c)
++{
++ int scl;
++
++ udelay(i2c->op->udelay);
++ scl = i2c->op->getscl(i2c);
++ udelay(i2c->op->udelay);
++ return scl;
++}
++
++/*
++ * I2C low-level protocol operations
++ *
++ */
++
++static inline void i2c_release(struct efx_i2c_interface *i2c)
++{
++ EFX_WARN_ON_PARANOID(!i2c->scl);
++ EFX_WARN_ON_PARANOID(!i2c->sda);
++ /* Just in case */
++ setscl(i2c, 1);
++ setsda(i2c, 1);
++ EFX_BUG_ON_PARANOID(getsda(i2c) != 1);
++ EFX_BUG_ON_PARANOID(getscl(i2c) != 1);
++}
++
++static inline void i2c_start(struct efx_i2c_interface *i2c)
++{
++ /* We may be restarting immediately after a {send,recv}_bit,
++ * so SCL will not necessarily already be high.
++ */
++ EFX_WARN_ON_PARANOID(!i2c->sda);
++ setscl(i2c, 1);
++ setsda(i2c, 0);
++ setscl(i2c, 0);
++ setsda(i2c, 1);
++}
++
++static inline void i2c_send_bit(struct efx_i2c_interface *i2c, int bit)
++{
++ EFX_WARN_ON_PARANOID(i2c->scl != 0);
++ setsda(i2c, bit);
++ setscl(i2c, 1);
++ setscl(i2c, 0);
++ setsda(i2c, 1);
++}
++
++static inline int i2c_recv_bit(struct efx_i2c_interface *i2c)
++{
++ int bit;
++
++ EFX_WARN_ON_PARANOID(i2c->scl != 0);
++ EFX_WARN_ON_PARANOID(!i2c->sda);
++ setscl(i2c, 1);
++ bit = getsda(i2c);
++ setscl(i2c, 0);
++ return bit;
++}
++
++static inline void i2c_stop(struct efx_i2c_interface *i2c)
++{
++ EFX_WARN_ON_PARANOID(i2c->scl != 0);
++ setsda(i2c, 0);
++ setscl(i2c, 1);
++ setsda(i2c, 1);
++}
++
++/*
++ * I2C mid-level protocol operations
++ *
++ */
++
++/* Sends a byte via the I2C bus and checks for an acknowledgement from
++ * the slave device.
++ */
++static int i2c_send_byte(struct efx_i2c_interface *i2c, u8 byte)
++{
++ int i;
++
++ /* Send byte */
++ for (i = 0; i < 8; i++) {
++ i2c_send_bit(i2c, !!(byte & 0x80));
++ byte <<= 1;
++ }
++
++ /* Check for acknowledgement from slave */
++ return (i2c_recv_bit(i2c) == 0 ? 0 : -EIO);
++}
++
++/* Receives a byte via the I2C bus and sends ACK/NACK to the slave device. */
++static u8 i2c_recv_byte(struct efx_i2c_interface *i2c, int ack)
++{
++ u8 value = 0;
++ int i;
++
++ /* Receive byte */
++ for (i = 0; i < 8; i++)
++ value = (value << 1) | i2c_recv_bit(i2c);
++
++ /* Send ACK/NACK */
++ i2c_send_bit(i2c, (ack ? 0 : 1));
++
++ return value;
++}
++
++/* Calculate command byte for a read operation */
++static inline u8 i2c_read_cmd(u8 device_id)
++{
++ return ((device_id << 1) | 1);
++}
++
++/* Calculate command byte for a write operation */
++static inline u8 i2c_write_cmd(u8 device_id)
++{
++ return ((device_id << 1) | 0);
++}
++
++int efx_i2c_check_presence(struct efx_i2c_interface *i2c, u8 device_id)
++{
++ int rc;
++
++ /* If someone is driving the bus low we just give up. */
++ if (getsda(i2c) == 0 || getscl(i2c) == 0) {
++ EFX_ERR(i2c->efx, "%s someone is holding the I2C bus low."
++ " Giving up.\n", __func__);
++ return -EFAULT;
++ }
++
++ /* Pretend to initiate a device write */
++ i2c_start(i2c);
++ rc = i2c_send_byte(i2c, i2c_write_cmd(device_id));
++ if (rc)
++ goto out;
++
++ out:
++ i2c_stop(i2c);
++ i2c_release(i2c);
++
++ return rc;
++}
++
++/* This performs a fast read of one or more consecutive bytes from an
++ * I2C device. Not all devices support consecutive reads of more than
++ * one byte; for these devices use efx_i2c_read() instead.
++ */
++int efx_i2c_fast_read(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len)
++{
++ int i;
++ int rc;
++
++ EFX_WARN_ON_PARANOID(getsda(i2c) != 1);
++ EFX_WARN_ON_PARANOID(getscl(i2c) != 1);
++ EFX_WARN_ON_PARANOID(data == NULL);
++ EFX_WARN_ON_PARANOID(len < 1);
++
++ /* Select device and starting offset */
++ i2c_start(i2c);
++ rc = i2c_send_byte(i2c, i2c_write_cmd(device_id));
++ if (rc)
++ goto out;
++ rc = i2c_send_byte(i2c, offset);
++ if (rc)
++ goto out;
++
++ /* Read data from device */
++ i2c_start(i2c);
++ rc = i2c_send_byte(i2c, i2c_read_cmd(device_id));
++ if (rc)
++ goto out;
++ for (i = 0; i < (len - 1); i++)
++ /* Read and acknowledge all but the last byte */
++ data[i] = i2c_recv_byte(i2c, 1);
++ /* Read last byte with no acknowledgement */
++ data[i] = i2c_recv_byte(i2c, 0);
++
++ out:
++ i2c_stop(i2c);
++ i2c_release(i2c);
++
++ return rc;
++}
++
++/* This performs a fast write of one or more consecutive bytes to an
++ * I2C device. Not all devices support consecutive writes of more
++ * than one byte; for these devices use efx_i2c_write() instead.
++ */
++int efx_i2c_fast_write(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ const u8 *data, unsigned int len)
++{
++ int i;
++ int rc;
++
++ EFX_WARN_ON_PARANOID(getsda(i2c) != 1);
++ EFX_WARN_ON_PARANOID(getscl(i2c) != 1);
++ EFX_WARN_ON_PARANOID(len < 1);
++
++ /* Select device and starting offset */
++ i2c_start(i2c);
++ rc = i2c_send_byte(i2c, i2c_write_cmd(device_id));
++ if (rc)
++ goto out;
++ rc = i2c_send_byte(i2c, offset);
++ if (rc)
++ goto out;
++
++ /* Write data to device */
++ for (i = 0; i < len; i++) {
++ rc = i2c_send_byte(i2c, data[i]);
++ if (rc)
++ goto out;
++ }
++
++ out:
++ i2c_stop(i2c);
++ i2c_release(i2c);
++
++ return rc;
++}
++
++/* I2C byte-by-byte read */
++int efx_i2c_read(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len)
++{
++ int rc;
++
++ /* i2c_fast_read with length 1 is a single byte read */
++ for (; len > 0; offset++, data++, len--) {
++ rc = efx_i2c_fast_read(i2c, device_id, offset, data, 1);
++ if (rc)
++ return rc;
++ }
++
++ return 0;
++}
++
++/* I2C byte-by-byte write */
++int efx_i2c_write(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, const u8 *data, unsigned int len)
++{
++ int rc;
++
++ /* i2c_fast_write with length 1 is a single byte write */
++ for (; len > 0; offset++, data++, len--) {
++ rc = efx_i2c_fast_write(i2c, device_id, offset, data, 1);
++ if (rc)
++ return rc;
++ mdelay(i2c->op->mdelay);
++ }
++
++ return 0;
++}
++
++
++/* This is just a slightly neater wrapper round efx_i2c_fast_write
++ * in the case where the target doesn't take an offset
++ */
++int efx_i2c_send_bytes(struct efx_i2c_interface *i2c,
++ u8 device_id, const u8 *data, unsigned int len)
++{
++ return efx_i2c_fast_write(i2c, device_id, data[0], data + 1, len - 1);
++}
++
++/* I2C receiving of bytes - does not send an offset byte */
++int efx_i2c_recv_bytes(struct efx_i2c_interface *i2c, u8 device_id,
++ u8 *bytes, unsigned int len)
++{
++ int i;
++ int rc;
++
++ EFX_WARN_ON_PARANOID(getsda(i2c) != 1);
++ EFX_WARN_ON_PARANOID(getscl(i2c) != 1);
++ EFX_WARN_ON_PARANOID(len < 1);
++
++ /* Select device */
++ i2c_start(i2c);
++
++ /* Read data from device */
++ rc = i2c_send_byte(i2c, i2c_read_cmd(device_id));
++ if (rc)
++ goto out;
++
++ for (i = 0; i < (len - 1); i++)
++ /* Read and acknowledge all but the last byte */
++ bytes[i] = i2c_recv_byte(i2c, 1);
++ /* Read last byte with no acknowledgement */
++ bytes[i] = i2c_recv_byte(i2c, 0);
++
++ out:
++ i2c_stop(i2c);
++ i2c_release(i2c);
++
++ return rc;
++}
++
++/* SMBus and some I2C devices will time out if the I2C clock is
++ * held low for too long. This is most likely to happen in virtualised
++ * systems (when the entire domain is descheduled) but could in
++ * principle happen due to preemption on any busy system (and given the
++ * potential length of an I2C operation turning preemption off is not
++ * a sensible option). The following functions deal with the failure by
++ * retrying up to a fixed number of times.
++ */
++
++#define I2C_MAX_RETRIES (10)
++
++/* The timeout problem will result in -EIO. If the wrapped function
++ * returns any other error, pass this up and do not retry. */
++#define RETRY_WRAPPER(_f) \
++ int retries = I2C_MAX_RETRIES; \
++ int rc; \
++ while (retries) { \
++ rc = _f; \
++ if (rc != -EIO) \
++ return rc; \
++ retries--; \
++ } \
++ return rc; \
++
++int efx_i2c_check_presence_retry(struct efx_i2c_interface *i2c, u8 device_id)
++{
++ RETRY_WRAPPER(efx_i2c_check_presence(i2c, device_id))
++}
++
++int efx_i2c_read_retry(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len)
++{
++ RETRY_WRAPPER(efx_i2c_read(i2c, device_id, offset, data, len))
++}
++
++int efx_i2c_write_retry(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, const u8 *data, unsigned int len)
++{
++ RETRY_WRAPPER(efx_i2c_write(i2c, device_id, offset, data, len))
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/i2c-direct.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/i2c-direct.h
+--- linux-2.6.18.8/drivers/net/sfc/i2c-direct.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/i2c-direct.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,108 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005: Fen Systems Ltd.
++ * Copyright 2006: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_I2C_DIRECT_H
++#define EFX_I2C_DIRECT_H
++
++#include "net_driver.h"
++
++/*
++ * Direct control of an I2C bus
++ */
++
++struct efx_i2c_interface;
++
++/**
++ * struct efx_i2c_bit_operations - I2C bus direct control methods
++ *
++ * I2C bus direct control methods.
++ *
++ * @setsda: Set state of SDA line
++ * @setscl: Set state of SCL line
++ * @getsda: Get state of SDA line
++ * @getscl: Get state of SCL line
++ * @udelay: Delay between each bit operation
++ * @mdelay: Delay between each byte write
++ */
++struct efx_i2c_bit_operations {
++ void (*setsda) (struct efx_i2c_interface *i2c);
++ void (*setscl) (struct efx_i2c_interface *i2c);
++ int (*getsda) (struct efx_i2c_interface *i2c);
++ int (*getscl) (struct efx_i2c_interface *i2c);
++ unsigned int udelay;
++ unsigned int mdelay;
++};
++
++/**
++ * struct efx_i2c_interface - an I2C interface
++ *
++ * An I2C interface.
++ *
++ * @efx: Attached Efx NIC
++ * @op: I2C bus control methods
++ * @sda: Current output state of SDA line
++ * @scl: Current output state of SCL line
++ */
++struct efx_i2c_interface {
++ struct efx_nic *efx;
++ struct efx_i2c_bit_operations *op;
++ unsigned int sda:1;
++ unsigned int scl:1;
++};
++
++extern int efx_i2c_check_presence(struct efx_i2c_interface *i2c, u8 device_id);
++extern int efx_i2c_fast_read(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ u8 *data, unsigned int len);
++extern int efx_i2c_fast_write(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ const u8 *data, unsigned int len);
++extern int efx_i2c_read(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len);
++extern int efx_i2c_write(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ const u8 *data, unsigned int len);
++
++extern int efx_i2c_send_bytes(struct efx_i2c_interface *i2c, u8 device_id,
++ const u8 *bytes, unsigned int len);
++
++extern int efx_i2c_recv_bytes(struct efx_i2c_interface *i2c, u8 device_id,
++ u8 *bytes, unsigned int len);
++
++
++/* Versions of the API that retry on failure. */
++extern int efx_i2c_check_presence_retry(struct efx_i2c_interface *i2c,
++ u8 device_id);
++
++extern int efx_i2c_read_retry(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset, u8 *data, unsigned int len);
++
++extern int efx_i2c_write_retry(struct efx_i2c_interface *i2c,
++ u8 device_id, u8 offset,
++ const u8 *data, unsigned int len);
++
++#endif /* EFX_I2C_DIRECT_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/Kconfig linux-2.6.18-xen-3.3.0/drivers/net/sfc/Kconfig
+--- linux-2.6.18.8/drivers/net/sfc/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,35 @@
++config SFC
++ tristate "Solarflare Solarstorm SFC4000 support"
++ depends on PCI && INET
++ select MII
++ help
++ This driver supports 10-gigabit Ethernet cards based on
++ the Solarflare Communications Solarstorm SFC4000 controller.
++
++ To compile this driver as a module, choose M here. The module
++ will be called sfc.
++
++config SFC_DEBUGFS
++ bool "Solarflare Solarstorm SFC4000 debugging support"
++ depends on SFC && DEBUG_FS
++ default N
++ help
++ This option creates an "sfc" subdirectory of debugfs with
++ debugging information for the SFC4000 driver.
++
++ If unsure, say N.
++
++config SFC_MTD
++ depends on SFC && MTD && MTD_PARTITIONS
++ tristate "Solarflare Solarstorm SFC4000 flash/EEPROM support"
++ help
++ This module exposes the on-board flash and/or EEPROM memory as
++ MTD devices (e.g. /dev/mtd1). This makes it possible to upload a
++ new boot ROM to the NIC.
++
++config SFC_RESOURCE
++ depends on SFC && X86
++ tristate "Solarflare Solarstorm SFC4000 resource driver"
++ help
++ This module provides the SFC resource manager driver.
++
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/kernel_compat.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/kernel_compat.c
+--- linux-2.6.18.8/drivers/net/sfc/kernel_compat.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/kernel_compat.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,654 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#define EFX_IN_KCOMPAT_C 1
++
++#include "net_driver.h"
++#include <linux/mii.h>
++#include <linux/ethtool.h>
++#include <linux/random.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include <linux/rtnetlink.h>
++#include <linux/bootmem.h>
++#include <asm/uaccess.h>
++#include "gmii.h"
++#include "ethtool.h"
++
++/*
++ * Kernel backwards compatibility
++ *
++ * This file provides functionality missing from earlier kernels.
++ */
++
++/**************************************************************************
++ *
++ * GMII-friendly versions of mii_ethtool_[gs]set
++ *
++ **************************************************************************
++ *
++ * Kernels prior to 2.6.12 don't support GMII PHYs via
++ * mii_ethtool_gset and mii_ethtool_sset. These are those functions
++ * taken from a 2.6.12 kernel tree, with the tests for
++ * mii->supports_gmii removed (since that field doesn't exist in older
++ * kernels).
++ *
++ */
++
++#ifdef EFX_NEED_MII_ETHTOOL_FIX
++int efx_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
++{
++ struct net_device *dev = mii->dev;
++ u32 advert, bmcr, lpa, nego;
++ u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
++
++ ecmd->supported =
++ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
++ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
++ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
++ ecmd->supported |= SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
++
++ /* only supports twisted-pair */
++ ecmd->port = PORT_MII;
++
++ /* only supports internal transceiver */
++ ecmd->transceiver = XCVR_INTERNAL;
++
++ /* this isn't fully supported at higher layers */
++ ecmd->phy_address = mii->phy_id;
++
++ ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
++ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
++ advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
++
++ if (advert & ADVERTISE_10HALF)
++ ecmd->advertising |= ADVERTISED_10baseT_Half;
++ if (advert & ADVERTISE_10FULL)
++ ecmd->advertising |= ADVERTISED_10baseT_Full;
++ if (advert & ADVERTISE_100HALF)
++ ecmd->advertising |= ADVERTISED_100baseT_Half;
++ if (advert & ADVERTISE_100FULL)
++ ecmd->advertising |= ADVERTISED_100baseT_Full;
++ if (advert2 & ADVERTISE_1000HALF)
++ ecmd->advertising |= ADVERTISED_1000baseT_Half;
++ if (advert2 & ADVERTISE_1000FULL)
++ ecmd->advertising |= ADVERTISED_1000baseT_Full;
++
++ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
++ lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
++ bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
++ lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
++ if (bmcr & BMCR_ANENABLE) {
++ ecmd->advertising |= ADVERTISED_Autoneg;
++ ecmd->autoneg = AUTONEG_ENABLE;
++
++ nego = mii_nway_result(advert & lpa);
++ if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) &
++ (lpa2 >> 2))
++ ecmd->speed = SPEED_1000;
++ else if (nego == LPA_100FULL || nego == LPA_100HALF)
++ ecmd->speed = SPEED_100;
++ else
++ ecmd->speed = SPEED_10;
++ if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL ||
++ nego == LPA_10FULL) {
++ ecmd->duplex = DUPLEX_FULL;
++ mii->full_duplex = 1;
++ } else {
++ ecmd->duplex = DUPLEX_HALF;
++ mii->full_duplex = 0;
++ }
++ } else {
++ ecmd->autoneg = AUTONEG_DISABLE;
++
++ ecmd->speed = ((bmcr & BMCR_SPEED1000 &&
++ (bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 :
++ (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10);
++ ecmd->duplex =
++ (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
++ }
++
++ /* ignore maxtxpkt, maxrxpkt for now */
++
++ return 0;
++}
++
++int efx_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
++{
++ struct net_device *dev = mii->dev;
++
++ if (ecmd->speed != SPEED_10 &&
++ ecmd->speed != SPEED_100 &&
++ ecmd->speed != SPEED_1000)
++ return -EINVAL;
++ if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
++ return -EINVAL;
++ if (ecmd->port != PORT_MII)
++ return -EINVAL;
++ if (ecmd->transceiver != XCVR_INTERNAL)
++ return -EINVAL;
++ if (ecmd->phy_address != mii->phy_id)
++ return -EINVAL;
++ if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
++ return -EINVAL;
++
++ /* ignore supported, maxtxpkt, maxrxpkt */
++
++ if (ecmd->autoneg == AUTONEG_ENABLE) {
++ u32 bmcr, advert, tmp;
++ u32 advert2 = 0, tmp2 = 0;
++
++ if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
++ ADVERTISED_10baseT_Full |
++ ADVERTISED_100baseT_Half |
++ ADVERTISED_100baseT_Full |
++ ADVERTISED_1000baseT_Half |
++ ADVERTISED_1000baseT_Full)) == 0)
++ return -EINVAL;
++
++ /* advertise only what has been requested */
++ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
++ tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
++ advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
++ tmp2 = advert2 & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
++ if (ecmd->advertising & ADVERTISED_10baseT_Half)
++ tmp |= ADVERTISE_10HALF;
++ if (ecmd->advertising & ADVERTISED_10baseT_Full)
++ tmp |= ADVERTISE_10FULL;
++ if (ecmd->advertising & ADVERTISED_100baseT_Half)
++ tmp |= ADVERTISE_100HALF;
++ if (ecmd->advertising & ADVERTISED_100baseT_Full)
++ tmp |= ADVERTISE_100FULL;
++ if (ecmd->advertising & ADVERTISED_1000baseT_Half)
++ tmp2 |= ADVERTISE_1000HALF;
++ if (ecmd->advertising & ADVERTISED_1000baseT_Full)
++ tmp2 |= ADVERTISE_1000FULL;
++ if (advert != tmp) {
++ mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
++ mii->advertising = tmp;
++ }
++ if (advert2 != tmp2)
++ mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2);
++
++ /* turn on autonegotiation, and force a renegotiate */
++ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
++ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
++ mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
++
++ mii->force_media = 0;
++ } else {
++ u32 bmcr, tmp;
++
++ /* turn off auto negotiation, set speed and duplexity */
++ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
++ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
++ BMCR_SPEED1000 | BMCR_FULLDPLX);
++ if (ecmd->speed == SPEED_1000)
++ tmp |= BMCR_SPEED1000;
++ else if (ecmd->speed == SPEED_100)
++ tmp |= BMCR_SPEED100;
++ if (ecmd->duplex == DUPLEX_FULL) {
++ tmp |= BMCR_FULLDPLX;
++ mii->full_duplex = 1;
++ } else {
++ mii->full_duplex = 0;
++ }
++ if (bmcr != tmp)
++ mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);
++
++ mii->force_media = 1;
++ }
++ return 0;
++}
++#endif /* NEED_EFX_MII_ETHTOOL_GSET */
++
++/**************************************************************************
++ *
++ * unregister_netdevice_notifier : Has a race before 2.6.17
++ *
++ **************************************************************************
++ *
++ */
++
++#ifdef EFX_NEED_UNREGISTER_NETDEVICE_NOTIFIER_FIX
++/**
++ * efx_unregister_netdevice_notifier - fixed unregister_netdevice_notifier
++ * @nb: notifier to unregister
++ *
++ * unregister_netdevice_notifier() does not wait for the notifier
++ * to be unused before 2.6.17. This wrapper fixes that.
++ */
++int efx_unregister_netdevice_notifier(struct notifier_block *nb)
++{
++ int res;
++
++ res = unregister_netdevice_notifier(nb);
++ /* Ensure any outstanding calls complete. */
++ rtnl_lock();
++ rtnl_unlock();
++ return res;
++}
++#endif /* NEED_EFX_UNREGISTER_NETDEVICE_NOTIFIER */
++
++/**************************************************************************
++ *
++ * IOMMU-locking versions of pci_[un]map_single and
++ * pci_{alloc,free}_consistent. See SFC bug 4560.
++ *
++ **************************************************************************
++ *
++ */
++#ifdef EFX_NEED_IOMMU_LOCK
++
++/*
++ * efx_use_iommu_lock - IOMMU lock use control
++ *
++ * If set to 1, the driver will attempt to mitigate the race condition
++ * bug around IOMMU accesses in some 2.6 kernels. If set to 2, the
++ * driver will use the lock even if it thinks it doesn't need to.
++ * Note that this is only a best-effort attempt; in particular, we
++ * cannot do anything about other drivers touching the IOMMU.
++ */
++static unsigned int efx_use_iommu_lock = 1;
++EXPORT_SYMBOL(efx_use_iommu_lock);
++
++/*
++ * efx_iommu_lock - lock around IOMMU accesses
++ *
++ * This spinlock should be held while calling functions that access
++ * the IOMMU if efx_use_iommu_lock is >= 2. The efx_pci_*()
++ * functions do this where possible.
++ */
++static spinlock_t efx_iommu_lock = SPIN_LOCK_UNLOCKED;
++EXPORT_SYMBOL(efx_iommu_lock);
++
++/* Don't use the IOMMU lock if the device can access the whole of memory */
++#define EFX_DMA_CONSISTENT(_efx) \
++ (((_efx)->dma_mask >> PAGE_SHIFT) >= max_pfn)
++/**
++ * efx_pci_map_single - map buffer for DMA, under IOMMU lock
++ * @pci: PCI device
++ * @ptr: Buffer
++ * @size: Buffer length
++ * @direction: DMA direction
++ *
++ * Wrapper for pci_map_single that uses efx_iommu_lock if necessary.
++ */
++dma_addr_t efx_pci_map_single(struct pci_dev *pci, void *ptr, size_t size,
++ int direction)
++{
++ struct efx_nic *efx = pci_get_drvdata(pci);
++ unsigned long flags __attribute__ ((unused));
++ dma_addr_t dma_addr;
++
++ if (unlikely((efx_use_iommu_lock &&
++ (!EFX_NO_IOMMU) &&
++ (!EFX_DMA_CONSISTENT(efx))) ||
++ efx_use_iommu_lock >= 2)) {
++ spin_lock_irqsave(&efx_iommu_lock, flags);
++ dma_addr = pci_map_single(pci, ptr, size, direction);
++ spin_unlock_irqrestore(&efx_iommu_lock, flags);
++ } else {
++ dma_addr = pci_map_single(pci, ptr, size, direction);
++ }
++ return dma_addr;
++}
++
++/**
++ * efx_pci_unmap_single - unmap buffer for DMA, under IOMMU lock
++ * @pci: PCI device
++ * @dma_addr: DMA address
++ * @size: Buffer length
++ * @direction: DMA direction
++ *
++ * Wrapper for pci_unmap_single that uses efx_iommu_lock if necessary.
++ */
++void efx_pci_unmap_single(struct pci_dev *pci, dma_addr_t dma_addr,
++ size_t size, int direction)
++{
++ struct efx_nic *efx = pci_get_drvdata(pci);
++ unsigned long flags __attribute__ ((unused));
++
++ if (unlikely((efx_use_iommu_lock &&
++ (!EFX_NO_IOMMU) &&
++ (!EFX_DMA_CONSISTENT(efx))) ||
++ efx_use_iommu_lock >= 2)) {
++ spin_lock_irqsave(&efx_iommu_lock, flags);
++ pci_unmap_single(pci, dma_addr, size, direction);
++ spin_unlock_irqrestore(&efx_iommu_lock, flags);
++ } else {
++ pci_unmap_single(pci, dma_addr, size, direction);
++ }
++}
++
++/**
++ * efx_pci_alloc_consistent - allocate DMA-consistent buffer, under IOMMU lock
++ * @pci: PCI device
++ * @size: Buffer length
++ * @dma_addr: DMA address
++ *
++ * Wrapper for pci_alloc_consistent that uses efx_iommu_lock if necessary.
++ *
++ * Bugs: Currently this can't use the spinlock because
++ * pci_alloc_consistent may block.
++ */
++void *efx_pci_alloc_consistent(struct pci_dev *pci, size_t size,
++ dma_addr_t *dma_addr)
++{
++ return pci_alloc_consistent(pci, size, dma_addr);
++}
++
++/**
++ * efx_pci_free_consistent - free DMA-consistent buffer, under IOMMU lock
++ * @pci: PCI device
++ * @size: Buffer length
++ * @ptr: Buffer
++ * @dma_addr: DMA address
++ *
++ * Wrapper for pci_free_consistent that uses efx_iommu_lock if necessary.
++ */
++void efx_pci_free_consistent(struct pci_dev *pci, size_t size, void *ptr,
++ dma_addr_t dma_addr)
++{
++ struct efx_nic *efx = pci_get_drvdata(pci);
++ unsigned long flags __attribute__ ((unused));
++
++ if (unlikely((efx_use_iommu_lock &&
++ (!EFX_NO_IOMMU) &&
++ (!EFX_DMA_CONSISTENT(efx))) ||
++ efx_use_iommu_lock >= 2)) {
++ spin_lock_irqsave(&efx_iommu_lock, flags);
++ pci_free_consistent(pci, size, ptr, dma_addr);
++ spin_unlock_irqrestore(&efx_iommu_lock, flags);
++ } else {
++ pci_free_consistent(pci, size, ptr, dma_addr);
++ }
++}
++
++module_param(efx_use_iommu_lock, uint, 0644);
++MODULE_PARM_DESC(efx_use_iommu_lock, "Enable lock for bug in free_iommu");
++
++#endif
++
++#ifdef EFX_NEED_COMPOUND_PAGE_FIX
++
++void efx_compound_page_destructor(struct page *page)
++{
++ /* Fake up page state to keep __free_pages happy */
++ set_page_count(page, 1);
++ page[1].mapping = NULL;
++
++ __free_pages(page, (unsigned long)page[1].index);
++}
++
++#endif /* NEED_COMPOUND_PAGE_FIX */
++
++/**************************************************************************
++ *
++ * print_hex_dump, taken from lib/hexdump.c.
++ *
++ **************************************************************************
++ *
++ */
++#ifdef EFX_NEED_HEX_DUMP
++
++#define hex_asc(x) "0123456789abcdef"[x]
++#define isascii(c) (((unsigned char)(c))<=0x7f)
++
++static void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
++ int groupsize, char *linebuf, size_t linebuflen,
++ int ascii)
++{
++ const u8 *ptr = buf;
++ u8 ch;
++ int j, lx = 0;
++ int ascii_column;
++
++ if (rowsize != 16 && rowsize != 32)
++ rowsize = 16;
++
++ if (!len)
++ goto nil;
++ if (len > rowsize) /* limit to one line at a time */
++ len = rowsize;
++ if ((len % groupsize) != 0) /* no mixed size output */
++ groupsize = 1;
++
++ switch (groupsize) {
++ case 8: {
++ const u64 *ptr8 = buf;
++ int ngroups = len / groupsize;
++
++ for (j = 0; j < ngroups; j++)
++ lx += scnprintf(linebuf + lx, linebuflen - lx,
++ "%16.16llx ", (unsigned long long)*(ptr8 + j));
++ ascii_column = 17 * ngroups + 2;
++ break;
++ }
++
++ case 4: {
++ const u32 *ptr4 = buf;
++ int ngroups = len / groupsize;
++
++ for (j = 0; j < ngroups; j++)
++ lx += scnprintf(linebuf + lx, linebuflen - lx,
++ "%8.8x ", *(ptr4 + j));
++ ascii_column = 9 * ngroups + 2;
++ break;
++ }
++
++ case 2: {
++ const u16 *ptr2 = buf;
++ int ngroups = len / groupsize;
++
++ for (j = 0; j < ngroups; j++)
++ lx += scnprintf(linebuf + lx, linebuflen - lx,
++ "%4.4x ", *(ptr2 + j));
++ ascii_column = 5 * ngroups + 2;
++ break;
++ }
++
++ default:
++ for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen;
++ j++) {
++ ch = ptr[j];
++ linebuf[lx++] = hex_asc(ch >> 4);
++ linebuf[lx++] = hex_asc(ch & 0x0f);
++ linebuf[lx++] = ' ';
++ }
++ ascii_column = 3 * rowsize + 2;
++ break;
++ }
++ if (!ascii)
++ goto nil;
++
++ while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
++ linebuf[lx++] = ' ';
++ /* Removed is_print() check */
++ for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++)
++ linebuf[lx++] = isascii(ptr[j]) ? ptr[j] : '.';
++nil:
++ linebuf[lx++] = '\0';
++}
++
++void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
++ int rowsize, int groupsize,
++ const void *buf, size_t len, int ascii)
++{
++ const u8 *ptr = buf;
++ int i, linelen, remaining = len;
++ char linebuf[200];
++
++ if (rowsize != 16 && rowsize != 32)
++ rowsize = 16;
++
++ for (i = 0; i < len; i += rowsize) {
++ linelen = min(remaining, rowsize);
++ remaining -= rowsize;
++ hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
++ linebuf, sizeof(linebuf), ascii);
++
++ switch (prefix_type) {
++ case DUMP_PREFIX_ADDRESS:
++ printk("%s%s%*p: %s\n", level, prefix_str,
++ (int)(2 * sizeof(void *)), ptr + i, linebuf);
++ break;
++ case DUMP_PREFIX_OFFSET:
++ printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
++ break;
++ default:
++ printk("%s%s%s\n", level, prefix_str, linebuf);
++ break;
++ }
++ }
++}
++
++#endif /* EFX_NEED_HEX_DUMP */
++
++/**************************************************************************
++ *
++ * print_mac, from net/ethernet/eth.c in v2.6.24
++ *
++ **************************************************************************
++ *
++ */
++#ifdef EFX_NEED_PRINT_MAC
++char *print_mac(char *buf, const u8 *addr)
++{
++ sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
++ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
++ return buf;
++}
++#endif /* EFX_NEED_PRINT_MAC */
++
++#ifdef EFX_NEED_CSUM_TCPUDP_NOFOLD
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++__wsum
++csum_tcpudp_nofold (__be32 saddr, __be32 daddr, unsigned short len,
++ unsigned short proto, __wsum sum)
++#else
++__wsum
++csum_tcpudp_nofold (unsigned long saddr, unsigned long daddr,
++ unsigned short len, unsigned short proto, __wsum sum)
++#endif
++{
++ unsigned long result;
++
++ result = (__force u64)saddr + (__force u64)daddr +
++ (__force u64)sum + ((len + proto) << 8);
++
++ /* Fold down to 32-bits so we don't lose in the typedef-less network stack. */
++ /* 64 to 33 */
++ result = (result & 0xffffffff) + (result >> 32);
++ /* 33 to 32 */
++ result = (result & 0xffffffff) + (result >> 32);
++ return (__force __wsum)result;
++
++}
++#endif /* EFX_NEED_CSUM_TCPUDP_NOFOLD */
++
++#ifdef EFX_NEED_RANDOM_ETHER_ADDR
++/* Generate random MAC address */
++void efx_random_ether_addr(uint8_t *addr) {
++ get_random_bytes (addr, ETH_ALEN);
++ addr [0] &= 0xfe; /* clear multicast bit */
++ addr [0] |= 0x02; /* set local assignment bit (IEEE802) */
++}
++#endif /* EFX_NEED_RANDOM_ETHER_ADDR */
++
++#ifdef EFX_NEED_MSECS_TO_JIFFIES
++/*
++ * When we convert to jiffies then we interpret incoming values
++ * the following way:
++ *
++ * - negative values mean 'infinite timeout' (MAX_JIFFY_OFFSET)
++ *
++ * - 'too large' values [that would result in larger than
++ * MAX_JIFFY_OFFSET values] mean 'infinite timeout' too.
++ *
++ * - all other values are converted to jiffies by either multiplying
++ * the input value by a factor or dividing it with a factor
++ *
++ * We must also be careful about 32-bit overflows.
++ */
++#ifndef MSEC_PER_SEC
++#define MSEC_PER_SEC 1000L
++#endif
++unsigned long msecs_to_jiffies(const unsigned int m)
++{
++ /*
++ * Negative value, means infinite timeout:
++ */
++ if ((int)m < 0)
++ return MAX_JIFFY_OFFSET;
++
++#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
++ /*
++ * HZ is equal to or smaller than 1000, and 1000 is a nice
++ * round multiple of HZ, divide with the factor between them,
++ * but round upwards:
++ */
++ return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
++#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
++ /*
++ * HZ is larger than 1000, and HZ is a nice round multiple of
++ * 1000 - simply multiply with the factor between them.
++ *
++ * But first make sure the multiplication result cannot
++ * overflow:
++ */
++ if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
++ return MAX_JIFFY_OFFSET;
++
++ return m * (HZ / MSEC_PER_SEC);
++#else
++ /*
++ * Generic case - multiply, round and divide. But first
++ * check that if we are doing a net multiplication, that
++ * we wouldnt overflow:
++ */
++ if (HZ > MSEC_PER_SEC && m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
++ return MAX_JIFFY_OFFSET;
++
++ return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
++#endif
++}
++#endif /* EFX_NEED_MSECS_TO_JIFFIES */
++
++#ifdef EFX_NEED_MSLEEP
++/**
++ * msleep - sleep safely even with waitqueue interruptions
++ * @msecs: Time in milliseconds to sleep for
++ */
++void msleep(unsigned int msecs)
++{
++ unsigned long timeout = msecs_to_jiffies(msecs) + 1;
++
++ while (timeout)
++ timeout = schedule_timeout_uninterruptible(timeout);
++}
++#endif
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/kernel_compat.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/kernel_compat.h
+--- linux-2.6.18.8/drivers/net/sfc/kernel_compat.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/kernel_compat.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,925 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_KERNEL_COMPAT_H
++#define EFX_KERNEL_COMPAT_H
++
++#include <linux/version.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/pci.h>
++#include <linux/workqueue.h>
++#include <linux/moduleparam.h>
++#include <linux/interrupt.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++
++#include "extraversion.h"
++
++/*
++ * Kernel backwards compatibility
++ *
++ * This file provides macros that enable the driver to be compiled on
++ * any kernel from 2.6.9 onward (plus SLES 9 2.6.5), without requiring
++ * explicit version tests scattered throughout the code.
++ */
++
++/**************************************************************************
++ *
++ * Version/config/architecture tests to set feature flags
++ *
++ **************************************************************************
++ *
++ * NOTE: For simplicity, these initial version tests cover kernel.org
++ * releases only. Backported features in "enterprise" kernels are
++ * handled further down.
++ */
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) && \
++ !(defined(EFX_DIST_SUSE) && \
++ LINUX_VERSION_CODE == KERNEL_VERSION(2,6,5) && \
++ EFX_DIST_KVER_LEVEL_1 == 7)
++ #error "This kernel version is now unsupported"
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
++ #define EFX_NEED_RANDOM_ETHER_ADDR yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)
++ #define EFX_NEED_I2C_CLASS_HWMON yes
++ #define EFX_NEED_IF_MII yes
++ #define EFX_NEED_MSLEEP yes
++ #define EFX_NEED_MSECS_TO_JIFFIES yes
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
++ #define EFX_USE_MTD_ERASE_FAIL_ADDR yes
++#else
++ #define EFX_NEED_MTD_ERASE_CALLBACK yes
++ #define EFX_NEED_DUMMY_PCI_DISABLE_MSI yes
++ #define EFX_NEED_DUMMY_MSIX yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
++ #define EFX_NEED_BYTEORDER_TYPES yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
++ #define EFX_NEED_MMIOWB yes
++ #define EFX_NEED_PCI_SAVE_RESTORE_WRAPPERS yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
++ #define EFX_NEED_DUMMY_SUPPORTS_GMII yes
++ #define EFX_NEED_MII_CONSTANTS yes
++ #define EFX_NEED_MII_ETHTOOL_FIX yes
++ #define EFX_HAVE_MSIX_TABLE_RESERVED yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
++ #define EFX_NEED_SCHEDULE_TIMEOUT_INTERRUPTIBLE yes
++ #define EFX_NEED_SCHEDULE_TIMEOUT_UNINTERRUPTIBLE yes
++ #define EFX_NEED_GFP_T yes
++ #define EFX_NEED_KZALLOC yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
++ #define EFX_NEED_SETUP_TIMER yes
++ #ifdef CONFIG_HUGETLB_PAGE
++ #define EFX_USE_COMPOUND_PAGES yes
++ #endif
++#else
++ #define EFX_USE_COMPOUND_PAGES yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++ #define EFX_NEED_MUTEX yes
++ #define EFX_NEED_SAFE_LISTS yes
++ #ifdef EFX_USE_COMPOUND_PAGES
++ #define EFX_NEED_COMPOUND_PAGE_FIX yes
++ #endif
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
++ #define EFX_NEED_UNREGISTER_NETDEVICE_NOTIFIER_FIX yes
++ #define EFX_NEED_DEV_NOTICE yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++ #define EFX_NEED_IRQF_FLAGS yes
++ #define EFX_NEED_NETDEV_ALLOC_SKB yes
++ /* Fedora backported 2.6.18 netdevice.h changes */
++ #ifndef NETIF_F_GSO
++ #define EFX_NEED_NETIF_TX_LOCK yes
++ #endif
++#else
++ #define EFX_USE_MTD_WRITESIZE yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++ #define EFX_NEED_IRQ_HANDLER_T yes
++ #define EFX_HAVE_IRQ_HANDLER_REGS yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++ #define EFX_NEED_WORK_API_WRAPPERS yes
++ #define EFX_USE_FASTCALL yes
++ #define EFX_NEED_CSUM_UNFOLDED yes
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++ /*
++ * debugfs was introduced earlier, but only supports sym-links
++ * from 2.6.21
++ */
++ #ifdef CONFIG_DEBUG_FS
++ #define EFX_USE_DEBUGFS yes
++ #endif
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
++ #define EFX_NEED_SKB_HEADER_MACROS yes
++ #define EFX_NEED_HEX_DUMP yes
++#else
++ #define EFX_USE_CANCEL_WORK_SYNC yes
++#endif
++
++#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,22)
++ #define EFX_NEED_HEX_DUMP_CONST_FIX yes
++#endif
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) && \
++ (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
++ #define EFX_USE_ETHTOOL_GET_PERM_ADDR yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
++ #ifdef __ia64__
++ /* csum_tcpudp_nofold() is extern but not exported */
++ #define EFX_NEED_CSUM_TCPUDP_NOFOLD yes
++ #endif
++#else
++ #define EFX_USE_PCI_DEV_REVISION yes
++ #define EFX_USE_CANCEL_DELAYED_WORK_SYNC yes
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
++ #define EFX_HAVE_OLD_NAPI yes
++ #define EFX_NEED_GENERIC_LRO yes
++ #define EFX_NEED_PRINT_MAC yes
++#else
++ #define EFX_USE_ETHTOOL_FLAGS yes
++#endif
++
++/*
++ * SFC Bug 4560: Some kernels leak IOMMU entries under heavy load. Use a
++ * spinlock to serialise access where possible to alleviate the
++ * problem.
++ *
++ * NB. The following definition is duplicated in
++ * the char driver. Please keep in sync.
++ */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) && \
++ defined(__x86_64__) && defined(CONFIG_SMP))
++ #define EFX_NEED_IOMMU_LOCK yes
++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
++ #if defined(CONFIG_GART_IOMMU)
++ #define EFX_NO_IOMMU no_iommu
++ #else
++ #define EFX_NO_IOMMU 1
++ #endif
++ #else
++ #define EFX_NO_IOMMU 0
++ #endif
++#endif
++
++#ifdef CONFIG_PPC64
++ /* __raw_writel and friends are broken on ppc64 */
++ #define EFX_NEED_RAW_READ_AND_WRITE_FIX yes
++#endif
++
++/**************************************************************************
++ *
++ * Exceptions for backported features
++ *
++ **************************************************************************
++ */
++
++/* RHEL4 */
++#if defined(EFX_DIST_RHEL) && LINUX_VERSION_CODE == KERNEL_VERSION(2,6,9)
++ #if EFX_DIST_KVER_LEVEL_1 >= 22
++ /* linux-2.6.9-mmiowb.patch */
++ #undef EFX_NEED_MMIOWB
++ #endif
++ #if EFX_DIST_KVER_LEVEL_1 >= 34
++ /* linux-2.6.9-net-mii-update.patch */
++ #undef EFX_NEED_DUMMY_SUPPORTS_GMII
++ #undef EFX_NEED_MII_CONSTANTS
++ #undef EFX_NEED_MII_ETHTOOL_FIX
++ /* linux-2.6.9-gfp_t-typedef.patch */
++ #undef EFX_NEED_GFP_T
++ /* linux-2.6.9-slab-update.patch */
++ #undef EFX_NEED_KZALLOC
++ #endif
++ #if EFX_DIST_KVER_LEVEL_1 >= 55
++ /* linux-2.6.18-sata-update.patch (ported from 2.6.18->2.6.9) */
++ #undef EFX_NEED_SCHEDULE_TIMEOUT_UNINTERRUPTIBLE
++ #undef EFX_NEED_IRQ_HANDLER_T
++ #endif
++#endif
++
++/* RHEL5 */
++#if defined(EFX_DIST_RHEL) && LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
++ #if EFX_DIST_KVER_LEVEL_1 >= 53
++ /* linux-2.6.18-sata-update.patch */
++ #undef EFX_NEED_SCHEDULE_TIMEOUT_UNINTERRUPTIBLE
++ #undef EFX_NEED_IRQ_HANDLER_T
++ #endif
++#endif
++
++#if defined(EFX_DIST_RHEL)
++ #if (LINUX_VERSION_CODE != KERNEL_VERSION(2,6,9)) && \
++ (LINUX_VERSION_CODE != KERNEL_VERSION(2,6,18))
++ #error "Unknown Red Hat Enterprise kernel version"
++ #endif
++#endif
++
++/* SLES9 */
++#if defined(EFX_DIST_SUSE) && LINUX_VERSION_CODE == KERNEL_VERSION(2,6,5) && \
++ EFX_DIST_KVER_LEVEL_1 == 7
++ #if EFX_DIST_KVER_LEVEL_2 >= 139
++ #undef EFX_NEED_MMIOWB
++ #endif
++ #if EFX_DIST_KVER_LEVEL_2 >= 191
++ #undef EFX_NEED_MSLEEP
++ #undef EFX_NEED_MSECS_TO_JIFFIES
++ #endif
++ #if EFX_DIST_KVER_LEVEL_2 >= 244
++ #undef EFX_NEED_BYTEORDER_TYPES
++ #endif
++ #if EFX_DIST_KVER_LEVEL_2 >= 252
++ #undef EFX_NEED_KZALLOC
++ #endif
++#endif
++
++/**************************************************************************
++ *
++ * Definitions of missing constants, types, functions and macros
++ *
++ **************************************************************************
++ *
++ */
++
++#ifndef DMA_40BIT_MASK
++ #define DMA_40BIT_MASK 0x000000ffffffffffULL
++#endif
++
++#ifndef spin_trylock_irqsave
++ #define spin_trylock_irqsave(lock, flags) \
++ ({ \
++ local_irq_save(flags); \
++ spin_trylock(lock) ? \
++ 1 : ({local_irq_restore(flags); 0;}); \
++ })
++#endif
++
++#ifndef raw_smp_processor_id
++ #define raw_smp_processor_id() (current_thread_info()->cpu)
++#endif
++
++#ifndef NETIF_F_LRO
++ #define NETIF_F_LRO 0
++#endif
++
++/* Cope with small changes in PCI constants between minor kernel revisions */
++#if PCI_X_STATUS != 4
++ #undef PCI_X_STATUS
++ #define PCI_X_STATUS 4
++ #undef PCI_X_STATUS_MAX_SPLIT
++ #define PCI_X_STATUS_MAX_SPLIT 0x03800000
++#endif
++
++#ifndef PCI_EXP_LNKSTA
++ #define PCI_EXP_LNKSTA 18 /* Link Status */
++#endif
++
++/* Used for struct pt_regs */
++#ifndef regs_return_value
++ #if defined(__x86_64__)
++ #define regs_return_value(regs) ((regs)->rax)
++ #elif defined(__i386__)
++ #define regs_return_value(regs) ((regs)->eax)
++ #elif defined(__ia64__)
++ #define regs_return_value(regs) ((regs)->r8)
++ #else
++ #error "Need definition for regs_return_value()"
++ #endif
++#endif
++
++#ifndef __GFP_COMP
++ #define __GFP_COMP 0
++#endif
++
++#ifndef __iomem
++ #define __iomem
++#endif
++
++#ifndef NET_IP_ALIGN
++ #define NET_IP_ALIGN 2
++#endif
++
++#ifndef PCI_CAP_ID_EXP
++#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
++#endif
++
++#ifndef PCI_EXP_FLAGS
++#define PCI_EXP_FLAGS 2 /* Capabilities register */
++#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Capability version */
++#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */
++#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */
++#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */
++#endif
++
++#ifndef PCI_EXP_DEVCAP
++#define PCI_EXP_DEVCAP 4 /* Device capabilities */
++#define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */
++#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */
++#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */
++#endif
++
++#ifndef PCI_EXP_DEVCTL
++#define PCI_EXP_DEVCTL 8 /* Device Control */
++#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
++#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
++#endif
++
++#ifndef PCI_EXP_LNKSTA
++#define PCI_EXP_LNKSTA 18 /* Link Status */
++#endif
++
++#ifndef NETDEV_TX_OK
++ #define NETDEV_TX_OK 0
++#endif
++
++#ifndef NETDEV_TX_BUSY
++ #define NETDEV_TX_BUSY 1
++#endif
++
++#ifndef __force
++ #define __force
++#endif
++
++#if ! defined(for_each_cpu_mask) && ! defined(CONFIG_SMP)
++ #define for_each_cpu_mask(cpu, mask) \
++ for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
++#endif
++
++/**************************************************************************/
++
++#ifdef EFX_NEED_IRQ_HANDLER_T
++ typedef irqreturn_t (*irq_handler_t)(int, void *, struct pt_regs *);
++#endif
++
++#ifdef EFX_NEED_I2C_CLASS_HWMON
++ #define I2C_CLASS_HWMON (1<<0)
++#endif
++
++#ifdef EFX_NEED_MII_CONSTANTS
++ #define MII_CTRL1000 0x09
++ #define MII_STAT1000 0x0a
++ #define BMCR_SPEED1000 0x0040
++ #define ADVERTISE_PAUSE_ASYM 0x0800
++ #define ADVERTISE_PAUSE_CAP 0x0400
++ #define LPA_PAUSE_ASYM 0x0800
++ #define LPA_PAUSE_CAP 0x0400
++ #define ADVERTISE_1000FULL 0x0200
++ #define ADVERTISE_1000HALF 0x0100
++ #define LPA_1000FULL 0x0800
++ #define LPA_1000HALF 0x0400
++#endif
++
++#ifdef EFX_NEED_DUMMY_SUPPORTS_GMII
++ #include <linux/mii.h>
++ /* Ugly; redirect nonexistent new field to an old unused field */
++ #undef supports_gmii
++ #define supports_gmii full_duplex
++#endif
++
++#ifdef EFX_NEED_SKB_HEADER_MACROS
++ #define skb_mac_header(skb) (skb)->mac.raw
++ #define skb_network_header(skb) (skb)->nh.raw
++ #define tcp_hdr(skb) (skb)->h.th
++ #define ip_hdr(skb) (skb)->nh.iph
++ #define skb_tail_pointer(skb) (skb)->tail
++#endif
++
++#ifdef EFX_NEED_RAW_READ_AND_WRITE_FIX
++ #include <asm/io.h>
++ static inline void
++ efx_raw_writeb(u8 value, volatile void __iomem *addr)
++ {
++ writeb(value, addr);
++ }
++ static inline void
++ efx_raw_writew(u16 value, volatile void __iomem *addr)
++ {
++ writew(le16_to_cpu(value), addr);
++ }
++ static inline void
++ efx_raw_writel(u32 value, volatile void __iomem *addr)
++ {
++ writel(le32_to_cpu(value), addr);
++ }
++ static inline void
++ efx_raw_writeq(u64 value, volatile void __iomem *addr)
++ {
++ writeq(le64_to_cpu(value), addr);
++ }
++ static inline u8
++ efx_raw_readb(const volatile void __iomem *addr)
++ {
++ return readb(addr);
++ }
++ static inline u16
++ efx_raw_readw(const volatile void __iomem *addr)
++ {
++ return cpu_to_le16(readw(addr));
++ }
++ static inline u32
++ efx_raw_readl(const volatile void __iomem *addr)
++ {
++ return cpu_to_le32(readl(addr));
++ }
++ static inline u64
++ efx_raw_readq(const volatile void __iomem *addr)
++ {
++ return cpu_to_le64(readq(addr));
++ }
++
++ #undef __raw_writeb
++ #undef __raw_writew
++ #undef __raw_writel
++ #undef __raw_writeq
++ #undef __raw_readb
++ #undef __raw_readw
++ #undef __raw_readl
++ #undef __raw_readq
++ #define __raw_writeb efx_raw_writeb
++ #define __raw_writew efx_raw_writew
++ #define __raw_writel efx_raw_writel
++ #define __raw_writeq efx_raw_writeq
++ #define __raw_readb efx_raw_readb
++ #define __raw_readw efx_raw_readw
++ #define __raw_readl efx_raw_readl
++ #define __raw_readq efx_raw_readq
++#endif
++
++#ifdef EFX_NEED_SCHEDULE_TIMEOUT_INTERRUPTIBLE
++ static inline signed long
++ schedule_timeout_interruptible(signed long timeout)
++ {
++ set_current_state(TASK_INTERRUPTIBLE);
++ return schedule_timeout(timeout);
++ }
++#endif
++
++#ifdef EFX_NEED_SCHEDULE_TIMEOUT_UNINTERRUPTIBLE
++ static inline signed long
++ schedule_timeout_uninterruptible(signed long timeout)
++ {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ return schedule_timeout(timeout);
++ }
++#endif
++
++#ifdef EFX_NEED_MMIOWB
++ #if defined(__i386__) || defined(__x86_64__)
++ #define mmiowb()
++ #elif defined(__ia64__)
++ #ifndef ia64_mfa
++ #define ia64_mfa() asm volatile ("mf.a" ::: "memory")
++ #endif
++ #define mmiowb ia64_mfa
++ #else
++ #error "Need definition for mmiowb()"
++ #endif
++#endif
++
++#ifdef EFX_NEED_KZALLOC
++ static inline void *kzalloc(size_t size, int flags)
++ {
++ void *buf = kmalloc(size, flags);
++ if (buf)
++ memset(buf, 0,size);
++ return buf;
++ }
++#endif
++
++#ifdef EFX_NEED_SETUP_TIMER
++ static inline void setup_timer(struct timer_list * timer,
++ void (*function)(unsigned long),
++ unsigned long data)
++ {
++ timer->function = function;
++ timer->data = data;
++ init_timer(timer);
++ }
++#endif
++
++#ifdef EFX_NEED_MUTEX
++ #define EFX_DEFINE_MUTEX(x) DECLARE_MUTEX(x)
++ #undef DEFINE_MUTEX
++ #define DEFINE_MUTEX EFX_DEFINE_MUTEX
++
++ #define efx_mutex semaphore
++ #undef mutex
++ #define mutex efx_mutex
++
++ #define efx_mutex_init(x) init_MUTEX(x)
++ #undef mutex_init
++ #define mutex_init efx_mutex_init
++
++ #define efx_mutex_destroy(x) do { } while(0)
++ #undef mutex_destroy
++ #define mutex_destroy efx_mutex_destroy
++
++ #define efx_mutex_lock(x) down(x)
++ #undef mutex_lock
++ #define mutex_lock efx_mutex_lock
++
++ #define efx_mutex_lock_interruptible(x) down_interruptible(x)
++ #undef mutex_lock_interruptible
++ #define mutex_lock_interruptible efx_mutex_lock_interruptible
++
++ #define efx_mutex_unlock(x) up(x)
++ #undef mutex_unlock
++ #define mutex_unlock efx_mutex_unlock
++
++ #define efx_mutex_trylock(x) (!down_trylock(x))
++ #undef mutex_trylock
++ #define mutex_trylock efx_mutex_trylock
++
++ static inline int efx_mutex_is_locked(struct efx_mutex *m)
++ {
++ /* NB. This is quite inefficient, but it's the best we
++ * can do with the semaphore API. */
++ if ( down_trylock(m) )
++ return 1;
++ /* Undo the effect of down_trylock. */
++ up(m);
++ return 0;
++ }
++ #undef mutex_is_locked
++ #define mutex_is_locked efx_mutex_is_locked
++#endif
++
++#ifndef NETIF_F_GSO
++ #define efx_gso_size tso_size
++ #undef gso_size
++ #define gso_size efx_gso_size
++ #define efx_gso_segs tso_segs
++ #undef gso_segs
++ #define gso_segs efx_gso_segs
++#endif
++
++#ifdef EFX_NEED_IRQF_FLAGS
++ #ifdef SA_PROBEIRQ
++ #define IRQF_PROBE_SHARED SA_PROBEIRQ
++ #else
++ #define IRQF_PROBE_SHARED 0
++ #endif
++ #define IRQF_SHARED SA_SHIRQ
++#endif
++
++#ifdef EFX_NEED_NETDEV_ALLOC_SKB
++ #ifndef NET_SKB_PAD
++ #define NET_SKB_PAD 16
++ #endif
++
++ static inline
++ struct sk_buff *netdev_alloc_skb(struct net_device *dev,
++ unsigned int length)
++ {
++ struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD,
++ GFP_ATOMIC | __GFP_COLD);
++ if (likely(skb)) {
++ skb_reserve(skb, NET_SKB_PAD);
++ skb->dev = dev;
++ }
++ return skb;
++ }
++#endif
++
++#ifdef EFX_NEED_NETIF_TX_LOCK
++ 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 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_unlock(struct net_device *dev)
++ {
++ dev->xmit_lock_owner = -1;
++ spin_unlock(&dev->xmit_lock);
++ }
++#endif
++
++#ifdef EFX_NEED_CSUM_UNFOLDED
++ typedef u32 __wsum;
++ #define csum_unfold(x) ((__force __wsum) x)
++#endif
++
++#ifdef EFX_NEED_HEX_DUMP
++ enum {
++ DUMP_PREFIX_NONE,
++ DUMP_PREFIX_ADDRESS,
++ DUMP_PREFIX_OFFSET
++ };
++#endif
++
++#ifdef EFX_NEED_PRINT_MAC
++ #define DECLARE_MAC_BUF(var) char var[18] __attribute__((unused))
++#endif
++
++#ifdef EFX_NEED_GFP_T
++ typedef unsigned int gfp_t;
++#endif
++
++#ifdef EFX_NEED_SAFE_LISTS
++ #define list_for_each_entry_safe_reverse(pos, n, head, member) \
++ for (pos = list_entry((head)->prev, typeof(*pos), member), \
++ n = list_entry(pos->member.prev, typeof(*pos), member); \
++ &pos->member != (head); \
++ pos = n, \
++ n = list_entry(n->member.prev, typeof(*n), member))
++#endif
++
++#ifdef EFX_NEED_DEV_NOTICE
++ #define dev_notice dev_warn
++#endif
++
++#ifdef EFX_NEED_IF_MII
++ #include <linux/mii.h>
++ static inline struct mii_ioctl_data *efx_if_mii ( struct ifreq *rq ) {
++ return ( struct mii_ioctl_data * ) &rq->ifr_ifru;
++ }
++ #undef if_mii
++ #define if_mii efx_if_mii
++#endif
++
++#ifdef EFX_NEED_MTD_ERASE_CALLBACK
++ #include <linux/mtd/mtd.h>
++ static inline void efx_mtd_erase_callback(struct erase_info *instr) {
++ if ( instr->callback )
++ instr->callback ( instr );
++ }
++ #undef mtd_erase_callback
++ #define mtd_erase_callback efx_mtd_erase_callback
++#endif
++
++#ifdef EFX_NEED_DUMMY_PCI_DISABLE_MSI
++ #include <linux/pci.h>
++ static inline void dummy_pci_disable_msi ( struct pci_dev *dev ) {
++ /* Do nothing */
++ }
++ #undef pci_disable_msi
++ #define pci_disable_msi dummy_pci_disable_msi
++#endif
++
++#ifdef EFX_NEED_DUMMY_MSIX
++ struct msix_entry {
++ u16 vector; /* kernel uses to write allocated vector */
++ u16 entry; /* driver uses to specify entry, OS writes */
++ };
++ static inline int pci_enable_msix(struct pci_dev* dev,
++ struct msix_entry *entries, int nvec)
++ {return -1;}
++ static inline void pci_disable_msix(struct pci_dev *dev) { /* Do nothing */}
++#endif
++
++#ifdef EFX_NEED_BYTEORDER_TYPES
++ typedef __u16 __be16;
++ typedef __u32 __be32;
++ typedef __u64 __be64;
++ typedef __u16 __le16;
++ typedef __u32 __le32;
++ typedef __u64 __le64;
++#endif
++
++/**************************************************************************
++ *
++ * Missing functions provided by kernel_compat.c
++ *
++ **************************************************************************
++ *
++ */
++#ifdef EFX_NEED_RANDOM_ETHER_ADDR
++ extern void efx_random_ether_addr(uint8_t *addr);
++ #ifndef EFX_IN_KCOMPAT_C
++ #undef random_ether_addr
++ #define random_ether_addr efx_random_ether_addr
++ #endif
++#endif
++
++#ifdef EFX_NEED_MII_ETHTOOL_FIX
++ extern int efx_mii_ethtool_gset(struct mii_if_info *mii,
++ struct ethtool_cmd *ecmd);
++ extern int efx_mii_ethtool_sset(struct mii_if_info *mii,
++ struct ethtool_cmd *ecmd);
++ #ifndef EFX_IN_KCOMPAT_C
++ #undef mii_ethtool_gset
++ #define mii_ethtool_gset efx_mii_ethtool_gset
++ #undef mii_ethtool_sset
++ #define mii_ethtool_sset efx_mii_ethtool_sset
++ #endif
++#endif
++
++#ifdef EFX_NEED_UNREGISTER_NETDEVICE_NOTIFIER_FIX
++ extern int efx_unregister_netdevice_notifier(struct notifier_block *nb);
++ #ifndef EFX_IN_KCOMPAT_C
++ #undef unregister_netdevice_notifier
++ #define unregister_netdevice_notifier \
++ efx_unregister_netdevice_notifier
++ #endif
++#endif
++
++#ifdef EFX_NEED_IOMMU_LOCK
++ extern dma_addr_t efx_pci_map_single(struct pci_dev *pci, void *ptr,
++ size_t size, int direction);
++ extern void efx_pci_unmap_single(struct pci_dev *pci,
++ dma_addr_t dma_addr, size_t size,
++ int direction);
++ extern void * efx_pci_alloc_consistent(struct pci_dev *pci,
++ size_t size,
++ dma_addr_t *dma_addr);
++ extern void efx_pci_free_consistent(struct pci_dev *pci,
++ size_t size, void *ptr,
++ dma_addr_t dma_addr);
++ #ifndef EFX_IN_KCOMPAT_C
++ #undef pci_map_single
++ #undef pci_unmap_single
++ #undef pci_alloc_consistent
++ #undef pci_free_consistent
++ #define pci_map_single efx_pci_map_single
++ #define pci_unmap_single efx_pci_unmap_single
++ #define pci_alloc_consistent efx_pci_alloc_consistent
++ #define pci_free_consistent efx_pci_free_consistent
++ #endif
++#endif
++
++#ifdef EFX_NEED_PRINT_MAC
++ extern char *print_mac(char *buf, const u8 *addr);
++#endif
++
++#ifdef EFX_NEED_COMPOUND_PAGE_FIX
++ extern void efx_compound_page_destructor(struct page *page);
++#endif
++
++#ifdef EFX_NEED_HEX_DUMP
++ extern void
++ print_hex_dump(const char *level, const char *prefix_str,
++ int prefix_type, int rowsize, int groupsize,
++ const void *buf, size_t len, int ascii);
++#endif
++
++#ifdef EFX_NEED_MSECS_TO_JIFFIES
++ extern unsigned long msecs_to_jiffies(const unsigned int m);
++#endif
++
++#ifdef EFX_NEED_MSLEEP
++ extern void msleep(unsigned int msecs);
++#endif
++
++/**************************************************************************
++ *
++ * Wrappers to fix bugs and parameter changes
++ *
++ **************************************************************************
++ *
++ */
++
++#ifdef EFX_NEED_PCI_SAVE_RESTORE_WRAPPERS
++ #define pci_save_state(_dev) \
++ pci_save_state(_dev, (_dev)->saved_config_space)
++
++ #define pci_restore_state(_dev) \
++ pci_restore_state(_dev, (_dev)->saved_config_space)
++#endif
++
++#ifdef EFX_NEED_WORK_API_WRAPPERS
++ /**
++ * queue_delayed_work in pre 2.6.20 can't rearm from inside
++ * the work member. So instead do a rather hacky sleep
++ */
++ #define delayed_work work_struct
++ #define INIT_DELAYED_WORK INIT_WORK
++
++ static int inline efx_queue_delayed_work(struct workqueue_struct *wq,
++ struct work_struct *work,
++ unsigned long delay)
++ {
++ if (unlikely(delay > 0))
++ schedule_timeout_uninterruptible(delay);
++ return queue_work(wq, work);
++ }
++ #define queue_delayed_work efx_queue_delayed_work
++
++ /**
++ * The old and new work-function prototypes just differ
++ * in the type of the pointer returned, so it's safe
++ * to cast between the prototypes.
++ */
++ typedef void (*efx_old_work_func_t)(void *p);
++
++ #undef INIT_WORK
++ #define INIT_WORK(_work, _func) \
++ do { \
++ INIT_LIST_HEAD(&(_work)->entry); \
++ (_work)->pending = 0; \
++ PREPARE_WORK((_work), \
++ (efx_old_work_func_t) (_func), \
++ (_work)); \
++ } while (0)
++#endif
++
++#ifdef EFX_HAVE_OLD_NAPI
++ #define napi_str napi_dev[0]
++
++ static inline void netif_napi_add(struct net_device *dev,
++ struct net_device *dummy,
++ int (*poll) (struct net_device *,
++ int *),
++ int weight)
++ {
++ dev->weight = weight;
++ dev->poll = poll;
++ }
++
++ #define napi_enable netif_poll_enable
++ #define napi_disable netif_poll_disable
++
++ #define netif_rx_complete(dev, dummy) netif_rx_complete(dev)
++#endif
++
++#ifdef EFX_NEED_COMPOUND_PAGE_FIX
++ static inline
++ struct page *efx_alloc_pages(gfp_t flags, unsigned int order)
++ {
++ struct page *p = alloc_pages(flags, order);
++ if ((flags & __GFP_COMP) && (p != NULL) && (order > 0))
++ p[1].mapping = (void *)efx_compound_page_destructor;
++ return p;
++ }
++ #undef alloc_pages
++ #define alloc_pages efx_alloc_pages
++
++ static inline
++ void efx_free_pages(struct page *p, unsigned int order)
++ {
++ if ((order > 0) && (page_count(p) == 1))
++ p[1].mapping = NULL;
++ __free_pages(p, order);
++ }
++ #define __free_pages efx_free_pages
++#endif
++
++#ifdef EFX_NEED_HEX_DUMP_CONST_FIX
++ #define print_hex_dump(v,s,t,r,g,b,l,a) \
++ print_hex_dump((v),(s),(t),(r),(g),(void*)(b),(l),(a))
++#endif
++
++#endif /* EFX_KERNEL_COMPAT_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/lm87_support.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/lm87_support.c
+--- linux-2.6.18.8/drivers/net/sfc/lm87_support.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/lm87_support.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,295 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************/
++
++#include "net_driver.h"
++#include "lm87_support.h"
++#include "workarounds.h"
++
++/* Setting this to 1 will cause efx_check_lm87 to dump the status when it
++ * detects an alarm. This will result in the canonical name (i.e. that in
++ * the LM87 data book) being printed for each set status bit, along with
++ * the reading for that sensor value, if applicable. If set to 0 only the
++ * raw status1 and status2 register values are printed. */
++#define LM87_VERBOSE_ALARMS 1
++
++/**************************************************************************
++ *
++ * Onboard LM87 temperature and voltage monitor
++ *
++ **************************************************************************
++ */
++
++/* LM87 channel mode: all current boards either do not use AIN1/FAN1 and 2
++ * or use them as AIN. */
++#define LM87_CHANNEL_MODE 0x16
++#define LM87_CHANNEL_AIN1 1
++#define LM87_CHANNEL_AIN2 2
++#define LM87_CHANNEL_INIT (LM87_CHANNEL_AIN2 | LM87_CHANNEL_AIN1)
++
++/* LM87 configuration register 1 */
++#define LM87_CONFIG_1 0x40
++#define LM87_START 0x01
++#define LM87_INTEN 0x02
++#define LM87_INITIALIZATION 0x80
++
++/* LM87 interrupt status register 1 */
++#define LM87_INT_STATUS_1 0x41
++
++/* LM87 interrupt status register 2 */
++#define LM87_INT_STATUS_2 0x42
++
++/* LM87 interrupt mask register 1 */
++#define LM87_INT_MASK_1 0x43
++
++/* LM87 interrupt mask register 2 */
++#define LM87_INT_MASK_2 0x44
++
++/* LM87 monitoring limits */
++#define LM87_LIMITS 0x2b
++
++
++int efx_probe_lm87(struct efx_nic *efx, int addr,
++ const u8 *limits, int nlimits, const u16 irqmask)
++{
++ struct efx_i2c_interface *i2c = &efx->i2c;
++ u8 byte;
++ int rc;
++
++ /* Check for onboard LM87 */
++ rc = efx_i2c_check_presence_retry(i2c, addr);
++ if (rc) {
++ /* Not an error to lack an LM87, but failure to probe the
++ * bus is worrying. */
++ if (rc == -EFAULT) {
++ EFX_ERR(efx, "Failed to probe I2C bus for LM87!\n");
++ return rc;
++ } else {
++ EFX_LOG(efx, "has no onboard LM87 chip\n");
++ return 0;
++ }
++ }
++ efx->board_info.lm87_addr = addr;
++ EFX_LOG(efx, "detected onboard LM87 chip at 0x%2x\n", addr);
++
++ /* Reset chip */
++ byte = LM87_INITIALIZATION;
++ rc = efx_i2c_write_retry(i2c, addr, LM87_CONFIG_1, &byte, 1);
++ if (rc) {
++ EFX_ERR(efx, "could not reset LM87\n");
++ return rc;
++ }
++
++ /* Configure channel mode: currently hardwire to make pins 5 and 6
++ * AIN1 and AIN2 rather than FAN1, FAN2. */
++ byte = LM87_CHANNEL_INIT;
++ rc = efx_i2c_write_retry(i2c, addr, LM87_CHANNEL_MODE, &byte, 1);
++ if (rc) {
++ EFX_ERR(efx, "could not program LM87 chan. mode\n");
++ return rc;
++ }
++
++ /* Configure limits */
++ rc = efx_i2c_write_retry(i2c, addr, LM87_LIMITS, limits, nlimits);
++ if (rc) {
++ EFX_ERR(efx, "could not program LM87 limits\n");
++ return rc;
++ }
++
++ /* Mask off unwanted interrupts */
++ byte = (irqmask & 0xff);
++ rc = efx_i2c_write_retry(i2c, addr, LM87_INT_MASK_1, &byte, 1);
++ if (rc) {
++ EFX_ERR(efx, "could not mask LM87 interrupts\n");
++ return rc;
++ }
++
++ byte = (irqmask >> 8);
++ rc = efx_i2c_write_retry(i2c, addr, LM87_INT_MASK_2, &byte, 1);
++ if (rc) {
++ EFX_ERR(efx, "could not mask LM87 interrupts\n");
++ return rc;
++ }
++
++ /* Start monitoring */
++ byte = LM87_START;
++ if (irqmask != EFX_LM87_NO_INTS)
++ byte |= LM87_INTEN;
++
++ rc = efx_i2c_write_retry(i2c, addr, LM87_CONFIG_1, &byte, 1);
++ if (rc) {
++ EFX_ERR(efx, "could not start LM87\n");
++ return rc;
++ }
++
++ return rc;
++}
++
++void efx_remove_lm87(struct efx_nic *efx)
++{
++ struct efx_i2c_interface *i2c = &efx->i2c;
++ u8 byte;
++
++ if (!efx->board_info.lm87_addr)
++ return;
++
++ /* Reset chip */
++ byte = LM87_INITIALIZATION;
++ if (efx_i2c_write_retry(i2c, efx->board_info.lm87_addr,
++ LM87_CONFIG_1, &byte, 1) != 0)
++ EFX_ERR(efx, "could not reset LM87 on exit\n");
++}
++
++#if LM87_VERBOSE_ALARMS
++/* Bit number to name mapping for status1 */
++static const char *lm_stat_names[] = {
++/* Status 1 contents */
++ "+2.5Vin",
++ "Vccp1",
++ "Vcc",
++ "+5Vin",
++ "Int. Temp.",
++ "Ext. Temp.",
++ "FAN1/AIN1",
++ "FAN2/AIN2",
++/* Status 2 contents */
++ "+12Vin",
++ "Vccp2",
++ "Reserved",
++ "Reserved",
++ "CI",
++ "THERM#",
++ "D1 Fault",
++ "D2 Fault"
++};
++
++/* Where to read the value corresponding to an alarm bit. */
++static const int lm_stat_regs[] = {
++ 0x20, 0x21, 0x22, 0x23, 0x27, 0x26, 0x28, 0x29,
++ 0x24, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
++};
++
++/* The positions of the alarm bits do not correspond exactly to the
++ * order of the limit values. Convert so the user only needs to maintain
++ * one array */
++static int lm_bit_to_lim[] = {
++ 0, /* 2.5V */
++ 1, /* Vccp1 */
++ 2, /* Vcc */
++ 3, /* 5V */
++ 7, /* Int temp. */
++ 6, /* Ext temp. */
++ 8, /* AIN1 */
++ 9, /* AIN2 */
++ 4, /* 12V */
++ 5 /* Vccp2 */
++};
++
++/* These are bit numbers. I feel justified in hardwiring the max. */
++static const int lm_stat_max = 16;
++
++static void lm87_show_alarm(struct efx_nic *efx, int bit)
++{
++ char valbuf[8];
++ u8 val;
++
++ if (lm_stat_regs[bit] != 0xff) {
++ efx_i2c_read_retry(&efx->i2c, efx->board_info.lm87_addr,
++ lm_stat_regs[bit], &val, 1);
++ sprintf(valbuf, "0x%02x ", val);
++ } else {
++ strcpy(valbuf, "---- ");
++ }
++ /* If the board code knows what this sensor is wired to, let it tell
++ * us, else just print the LM87 datasheet name of the input, and the
++ * value. */
++ if (efx->board_info.interpret_sensor == NULL ||
++ (bit < ARRAY_SIZE(lm_bit_to_lim) &&
++ efx->board_info.interpret_sensor(efx, lm_bit_to_lim[bit], val)
++ == 0))
++ EFX_ERR(efx, ": %10s %4s\n",
++ STRING_TABLE_LOOKUP(bit, lm_stat), valbuf);
++}
++
++static void lm87_dump_alarms(struct efx_nic *efx, int stat1, int stat2)
++{
++ int i;
++ EFX_ERR(efx, " NAME value\n");
++ for (i = 0; i < 8; i++) {
++ if (stat1 & (1 << i))
++ lm87_show_alarm(efx, i);
++ if (stat2 & (1 << i))
++ lm87_show_alarm(efx, i + 8);
++ }
++}
++
++#else
++#define lm87_dump_alarms(_name, _stat1, _stat2) do {} while (0)
++#endif
++
++/* Read onboard LM87 (if present)
++ * Return error code if lm87 could not be read (-EIO)
++ * _or_ is raising an alarm (-ERANGE). 0 if AOK.
++ */
++int efx_check_lm87(struct efx_nic *efx, unsigned mask)
++{
++ struct efx_i2c_interface *i2c = &efx->i2c;
++ u8 int_status_1, int_status_2;
++ unsigned ints;
++ int rc = 0;
++
++ /* If link is up then do not monitor temperature */
++ if (EFX_WORKAROUND_7884(efx) && efx->link_up)
++ return 0;
++
++ if (!efx->board_info.lm87_addr)
++ return 0;
++
++ /* Read interrupt status registers */
++ rc = efx_i2c_read_retry(i2c, efx->board_info.lm87_addr,
++ LM87_INT_STATUS_1, &int_status_1, 1);
++ if (rc) {
++ EFX_ERR(efx, "could not read LM87 INT status 1\n");
++ return rc;
++ }
++ rc = efx_i2c_read_retry(i2c, efx->board_info.lm87_addr,
++ LM87_INT_STATUS_2, &int_status_2, 1);
++ if (rc) {
++ EFX_ERR(efx, "could not read LM87 INT status 2\n");
++ return rc;
++ }
++
++ int_status_1 &= mask;
++ int_status_2 &= (mask >> 8);
++ ints = ((int_status_2 << 8) | int_status_1);
++
++ /* Check interrupt status */
++ if (ints == 0)
++ return 0;
++
++ EFX_ERR(efx, "LM87 detected a hardware failure (status %02x:%02x)\n",
++ int_status_1, int_status_2);
++ lm87_dump_alarms(efx, int_status_1, int_status_2);
++
++ return -ERANGE;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/lm87_support.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/lm87_support.h
+--- linux-2.6.18.8/drivers/net/sfc/lm87_support.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/lm87_support.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,58 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************/
++
++#ifndef EFX_LM87_SUPPORT_H
++#define EFX_LM87_SUPPORT_H
++
++/* The interrupt bit masks. These are the same in the interrupt status and
++ * interrupt mask registers. */
++/* Register 1 bits */
++#define EFX_LM87_2_5V_INT (1)
++#define EFX_LM87_VCCP1_INT (2)
++#define EFX_LM87_VCC_INT (4)
++#define EFX_LM87_5_V_INT (8)
++#define EFX_LM87_ITMP_INT (0x10)
++#define EFX_LM87_ETMP_INT (0x20)
++#define EFX_LM87_FAN1_INT (0x40)
++#define EFX_LM87_FAN2_INT (0x80)
++/* Register 2 bits */
++#define EFX_LM87_12V_INT (0x100)
++#define EFX_LM87_VCCP2_INT (0x200)
++/* Bits 2 and 3 are reserved. */
++#define EFX_LM87_CI_INT (0x1000)
++#define EFX_LM87_THERM_INT (0x2000)
++#define EFX_LM87_D1_INT (0x4000)
++#define EFX_LM87_D2_INT (0x8000)
++
++#define EFX_LM87_NO_INTS ((u16)-1)
++
++extern
++int efx_probe_lm87(struct efx_nic *efx, int addr, const u8 *limits,
++ int nlimits, const u16 irqmask);
++
++extern void efx_remove_lm87(struct efx_nic *efx);
++
++extern int efx_check_lm87(struct efx_nic *efx, unsigned mask);
++
++#endif /* EFX_LM87_SUPPORT_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/mac.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/mac.h
+--- linux-2.6.18.8/drivers/net/sfc/mac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/mac.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,38 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_MAC_H
++#define EFX_MAC_H
++
++#include "net_driver.h"
++
++extern void mentormac_reset(struct efx_nic *efx);
++extern void mentormac_reconfigure(struct efx_nic *efx);
++extern struct efx_mac_operations falcon_gmac_operations;
++extern struct efx_mac_operations falcon_xmac_operations;
++
++#endif
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/Makefile linux-2.6.18-xen-3.3.0/drivers/net/sfc/Makefile
+--- linux-2.6.18.8/drivers/net/sfc/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,43 @@
++
++# Final objects
++sfc_o = sfc.o
++sfc_mtd_o = sfc_mtd.o
++
++# Constituent objects
++sfc_elements_o :=
++sfc_elements_o += efx.o
++sfc_elements_o += falcon.o
++sfc_elements_o += tx.o
++sfc_elements_o += rx.o
++sfc_elements_o += mentormac.o
++sfc_elements_o += falcon_gmac.o
++sfc_elements_o += falcon_xmac.o
++sfc_elements_o += alaska.o
++sfc_elements_o += i2c-direct.o
++sfc_elements_o += selftest.o
++sfc_elements_o += driverlink.o
++ifeq ($(CONFIG_SFC_DEBUGFS),y)
++sfc_elements_o += debugfs.o
++endif
++sfc_elements_o += ethtool.o
++sfc_elements_o += xfp_phy.o
++sfc_elements_o += mdio_10g.o
++sfc_elements_o += txc43128_phy.o
++sfc_elements_o += tenxpress.o
++sfc_elements_o += lm87_support.o
++sfc_elements_o += boards.o
++sfc_elements_o += sfe4001.o
++sfc_elements_o += pm8358_phy.o
++sfc_elements_o += null_phy.o
++sfc_elements_o += phy.o
++sfc_elements_o += kernel_compat.o
++
++sfc_mtd_elements_o := mtd.o
++
++obj-$(CONFIG_SFC) += $(sfc_o)
++obj-$(CONFIG_SFC_MTD) += $(sfc_mtd_o)
++
++sfc-objs = $(sfc_elements_o)
++sfc_mtd-objs = $(sfc_mtd_elements_o)
++
++obj-$(CONFIG_SFC_RESOURCE) += sfc_resource/
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/mdio_10g.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/mdio_10g.c
+--- linux-2.6.18.8/drivers/net/sfc/mdio_10g.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/mdio_10g.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,441 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++/*
++ * Useful functions for working with MDIO clause 45 PHYs
++ */
++#include <linux/types.h>
++#include <linux/ethtool.h>
++#include <linux/delay.h>
++#include "net_driver.h"
++#include "mdio_10g.h"
++#include "boards.h"
++
++static const char *mmd_block_names[] = {
++ [0] = "(illegal)",
++ [MDIO_MMD_PMAPMD] = "PMA/PMD",
++ [MDIO_MMD_WIS] = "WIS",
++ [MDIO_MMD_PCS] = "PCS",
++ [MDIO_MMD_PHYXS] = "PHY XS",
++ [MDIO_MMD_DTEXS] = "DTE XS",
++ [MDIO_MMD_TC] = "TC",
++ [MDIO_MMD_AN] = "AN",
++};
++static const int mmd_block_max = ARRAY_SIZE(mmd_block_names);
++
++const char *mdio_clause45_mmd_name(int mmd)
++{
++ return STRING_TABLE_LOOKUP(mmd, mmd_block);
++}
++
++int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd,
++ int spins, int spintime)
++{
++ u32 ctrl;
++ int phy_id = port->mii.phy_id;
++
++ /* Catch callers passing values in the wrong units (or just silly) */
++ EFX_BUG_ON_PARANOID(spins * spintime >= 5000);
++
++ mdio_clause45_write(port, phy_id, mmd, MDIO_MMDREG_CTRL1,
++ (1 << MDIO_MMDREG_CTRL1_RESET_LBN));
++ /* Wait for the reset bit to clear. */
++ do {
++ msleep(spintime);
++ ctrl = mdio_clause45_read(port, phy_id, mmd, MDIO_MMDREG_CTRL1);
++ spins--;
++
++ } while (spins && (ctrl & (1 << MDIO_MMDREG_CTRL1_RESET_LBN)));
++
++ return spins ? spins : -ETIMEDOUT;
++}
++
++static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd,
++ int fault_fatal)
++{
++ int status;
++ int phy_id = efx->mii.phy_id;
++ const char *mmdname = STRING_TABLE_LOOKUP(mmd, mmd_block);
++
++ if (LOOPBACK_INTERNAL(efx))
++ return 0;
++
++ /* Read MMD STATUS2 to check it is responding. */
++ status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2);
++ if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) &
++ ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) !=
++ MDIO_MMDREG_STAT2_PRESENT_VAL) {
++ EFX_ERR(efx, "PHY MMD %s not responding.\n", mmdname);
++ return -EIO;
++ }
++
++ /* Read MMD STATUS 1 to check for fault. */
++ status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT1);
++ if ((status & (1 << MDIO_MMDREG_STAT1_FAULT_LBN)) != 0) {
++ if (fault_fatal) {
++ EFX_ERR(efx, "PHY MMD %s reporting fatal"
++ " fault: status %x\n", mmdname, status);
++ return -EIO;
++ } else {
++ EFX_LOG(efx, "PHY MMD %s reporting status"
++ " %x (expected)\n", mmdname, status);
++ }
++ }
++ return 0;
++}
++
++/* This ought to be ridiculous overkill. We expect it to fail rarely */
++#define MDIO45_RESET_TIME HZ
++#define MDIO45_RESET_ITERS (100)
++
++int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
++ unsigned int mmd_mask)
++{
++ const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS;
++ int tries = MDIO45_RESET_ITERS;
++ int rc = 0;
++ int in_reset;
++
++ while (tries) {
++ int mask = mmd_mask;
++ int mmd = 0;
++ int stat;
++ in_reset = 0;
++ while (mask) {
++ if (mask & 1) {
++ stat = mdio_clause45_read(efx,
++ efx->mii.phy_id,
++ mmd,
++ MDIO_MMDREG_CTRL1);
++ if (stat < 0) {
++ EFX_ERR(efx, "failed to read"
++ " status of MMD %s\n",
++ STRING_TABLE_LOOKUP(mmd,
++ mmd_block));
++ return -EIO;
++ }
++ if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))
++ in_reset |= (1 << mmd);
++ }
++ mask = mask >> 1;
++ mmd++;
++ }
++ if (!in_reset)
++ break;
++ tries--;
++ msleep(spintime);
++ }
++ if (in_reset != 0) {
++ EFX_ERR(efx, "not all MMDs came out of reset in time."
++ " MMDs still in reset: %x\n", in_reset);
++ rc = -ETIMEDOUT;
++ }
++ return rc;
++}
++
++int mdio_clause45_check_mmds(struct efx_nic *efx,
++ unsigned int mmd_mask, unsigned int fatal_mask)
++{
++ int devices, mmd = 0;
++ int probe_mmd;
++
++ /* Historically we have probed the PHYXS to find out what devices are
++ * present,but that doesn't work so well if the PHYXS isn't expected
++ * to exist, if so just find the first item in the list supplied. */
++ probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS0_PHYXS) ? MDIO_MMD_PHYXS :
++ __ffs(mmd_mask);
++ devices = mdio_clause45_read(efx, efx->mii.phy_id,
++ probe_mmd, MDIO_MMDREG_DEVS0);
++
++ /* Check all the expected MMDs are present */
++ if (devices < 0) {
++ EFX_ERR(efx, "failed to read devices present\n");
++ return -EIO;
++ }
++ if ((devices & mmd_mask) != mmd_mask) {
++ EFX_ERR(efx, "required MMDs not present: got %x, "
++ "wanted %x\n", devices, mmd_mask);
++ return -ENODEV;
++ }
++ EFX_TRACE(efx, "Devices present: %x\n", devices);
++
++ /* Check all required MMDs are responding and happy. */
++ while (mmd_mask) {
++ if (mmd_mask & 1) {
++ int fault_fatal = fatal_mask & 1;
++ if (mdio_clause45_check_mmd(efx, mmd, fault_fatal))
++ return -EIO;
++ }
++ mmd_mask = mmd_mask >> 1;
++ fatal_mask = fatal_mask >> 1;
++ mmd++;
++ }
++
++ return 0;
++}
++
++int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
++{
++ int phy_id = efx->mii.phy_id;
++ int status;
++ int ok = 1;
++ int mmd = 0;
++ int good;
++
++ /* If the port is in loopback, then we should only consider a subset
++ * of mmd's */
++ if (LOOPBACK_INTERNAL(efx))
++ return 1;
++ else if (efx->loopback_mode == LOOPBACK_NETWORK)
++ return 0;
++ else if (!efx->phy_powered)
++ return 0;
++ else if (efx->loopback_mode == LOOPBACK_PHYXS)
++ mmd_mask &= ~(MDIO_MMDREG_DEVS0_PHYXS |
++ MDIO_MMDREG_DEVS0_PCS |
++ MDIO_MMDREG_DEVS0_PMAPMD);
++ else if (efx->loopback_mode == LOOPBACK_PCS)
++ mmd_mask &= ~(MDIO_MMDREG_DEVS0_PCS |
++ MDIO_MMDREG_DEVS0_PMAPMD);
++ else if (efx->loopback_mode == LOOPBACK_PMAPMD)
++ mmd_mask &= ~MDIO_MMDREG_DEVS0_PMAPMD;
++
++ while (mmd_mask) {
++ if (mmd_mask & 1) {
++ /* Double reads because link state is latched, and a
++ * read moves the current state into the register */
++ status = mdio_clause45_read(efx, phy_id,
++ mmd, MDIO_MMDREG_STAT1);
++ status = mdio_clause45_read(efx, phy_id,
++ mmd, MDIO_MMDREG_STAT1);
++
++ good = status & (1 << MDIO_MMDREG_STAT1_LINK_LBN);
++ ok = ok && good;
++ }
++ mmd_mask = (mmd_mask >> 1);
++ mmd++;
++ }
++ return ok;
++}
++
++void mdio_clause45_transmit_disable(struct efx_nic *efx, int disable)
++{
++ int phy_id = efx->mii.phy_id;
++ int ctrl1, ctrl2;
++
++ ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
++ MDIO_MMDREG_TXDIS);
++ if (disable)
++ ctrl2 |= (1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
++ else
++ ctrl1 &= ~(1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
++ if (ctrl1 != ctrl2)
++ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
++ MDIO_MMDREG_TXDIS, ctrl2);
++}
++
++void mdio_clause45_phy_reconfigure(struct efx_nic *efx)
++{
++ int phy_id = efx->mii.phy_id;
++ int ctrl1, ctrl2;
++
++ /* Handle (with debouncing) PMA/PMD loopback */
++ ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
++ MDIO_MMDREG_CTRL1);
++
++ if (efx->loopback_mode == LOOPBACK_PMAPMD)
++ ctrl2 |= (1 << MDIO_PMAPMD_CTRL1_LBACK_LBN);
++ else
++ ctrl2 &= ~(1 << MDIO_PMAPMD_CTRL1_LBACK_LBN);
++
++ if (ctrl1 != ctrl2)
++ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
++ MDIO_MMDREG_CTRL1, ctrl2);
++
++ /* Handle (with debouncing) PCS loopback */
++ ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
++ MDIO_MMDREG_CTRL1);
++ if (efx->loopback_mode == LOOPBACK_PCS)
++ ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
++ else
++ ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
++
++ if (ctrl1 != ctrl2)
++ mdio_clause45_write(efx, phy_id, MDIO_MMD_PCS,
++ MDIO_MMDREG_CTRL1, ctrl2);
++
++ /* Handle (with debouncing) PHYXS network loopback */
++ ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
++ MDIO_MMDREG_CTRL1);
++ if (efx->loopback_mode == LOOPBACK_NETWORK)
++ ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
++ else
++ ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
++
++ if (ctrl1 != ctrl2)
++ mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS,
++ MDIO_MMDREG_CTRL1, ctrl2);
++}
++
++static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx,
++ int lpower, int mmd)
++{
++ const char *mmdname = STRING_TABLE_LOOKUP(mmd, mmd_block);
++ int phy = efx->mii.phy_id;
++ int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1);
++ int ctrl1, ctrl2;
++
++ EFX_TRACE(efx, "Setting low power mode for MMD %s to %d\n",
++ mmdname, lpower);
++
++ if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) {
++ ctrl1 = ctrl2 = mdio_clause45_read(efx, phy,
++ mmd, MDIO_MMDREG_CTRL1);
++ if (lpower)
++ ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LPOWER_LBN);
++ else
++ ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LPOWER_LBN);
++ if (ctrl1 != ctrl2)
++ mdio_clause45_write(efx, phy, mmd,
++ MDIO_MMDREG_CTRL1, ctrl2);
++ } else {
++ /* If we ever want a completely generic PHY driver
++ * that which just does clause 45, we may consider not
++ * complaining, but for now expect the driver to know
++ * which MMDs to apply this to. */
++ EFX_ERR(efx, "Attempt change power setting of MMD %s"
++ " which doesn't support it.\n", mmdname);
++ }
++}
++
++void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
++ int low_power, unsigned int mmd_mask)
++{
++ int mmd = 0;
++ while (mmd_mask) {
++ if (mmd_mask & 1)
++ mdio_clause45_set_mmd_lpower(efx, low_power, mmd);
++ mmd_mask = (mmd_mask >> 1);
++ mmd++;
++ }
++}
++
++/**
++ * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO.
++ * @efx: Efx NIC
++ * @ecmd: Buffer for settings
++ *
++ * On return the 'port', 'speed', 'supported' and 'advertising' fields of
++ * ecmd have been filled out based on the PMA type.
++ */
++void mdio_clause45_get_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd)
++{
++ int pma_type;
++
++ /* If no PMA is present we are presumably talking something XAUI-ish
++ * like CX4. Which we report as FIBRE (see below) */
++ if ((efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)) == 0) {
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_FIBRE;
++ ecmd->supported = SUPPORTED_FIBRE;
++ ecmd->advertising = ADVERTISED_FIBRE;
++ return;
++ }
++
++ pma_type = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL2);
++ pma_type &= MDIO_PMAPMD_CTRL2_TYPE_MASK;
++
++ switch (pma_type) {
++ /* We represent CX4 as fibre in the absence of anything
++ better. */
++ case MDIO_PMAPMD_CTRL2_10G_CX4:
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_FIBRE;
++ ecmd->supported = SUPPORTED_FIBRE;
++ ecmd->advertising = ADVERTISED_FIBRE;
++ break;
++ /* 10G Base-T */
++ case MDIO_PMAPMD_CTRL2_10G_BT:
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_TP;
++ ecmd->supported = SUPPORTED_TP | SUPPORTED_10000baseT_Full;
++ ecmd->advertising = (ADVERTISED_FIBRE
++ | ADVERTISED_10000baseT_Full);
++ break;
++ case MDIO_PMAPMD_CTRL2_1G_BT:
++ ecmd->speed = SPEED_1000;
++ ecmd->port = PORT_TP;
++ ecmd->supported = SUPPORTED_TP | SUPPORTED_1000baseT_Full;
++ ecmd->advertising = (ADVERTISED_FIBRE
++ | ADVERTISED_1000baseT_Full);
++ break;
++ case MDIO_PMAPMD_CTRL2_100_BT:
++ ecmd->speed = SPEED_100;
++ ecmd->port = PORT_TP;
++ ecmd->supported = SUPPORTED_TP | SUPPORTED_100baseT_Full;
++ ecmd->advertising = (ADVERTISED_FIBRE
++ | ADVERTISED_100baseT_Full);
++ break;
++ case MDIO_PMAPMD_CTRL2_10_BT:
++ ecmd->speed = SPEED_10;
++ ecmd->port = PORT_TP;
++ ecmd->supported = SUPPORTED_TP | SUPPORTED_10baseT_Full;
++ ecmd->advertising = ADVERTISED_FIBRE | ADVERTISED_10baseT_Full;
++ break;
++ /* All the other defined modes are flavours of
++ * 10G optical */
++ default:
++ ecmd->speed = SPEED_10000;
++ ecmd->port = PORT_FIBRE;
++ ecmd->supported = SUPPORTED_FIBRE;
++ ecmd->advertising = ADVERTISED_FIBRE;
++ break;
++ }
++}
++
++/**
++ * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO.
++ * @efx: Efx NIC
++ * @ecmd: New settings
++ *
++ * Currently this just enforces that we are _not_ changing the
++ * 'port', 'speed', 'supported' or 'advertising' settings as these
++ * cannot be changed on any currently supported PHY.
++ */
++int mdio_clause45_set_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd)
++{
++ struct ethtool_cmd tmpcmd;
++ mdio_clause45_get_settings(efx, &tmpcmd);
++ /* None of the current PHYs support more than one mode
++ * of operation (and only 10GBT ever will), so keep things
++ * simple for now */
++ if ((ecmd->speed == tmpcmd.speed) && (ecmd->port == tmpcmd.port) &&
++ (ecmd->supported == tmpcmd.supported) &&
++ (ecmd->advertising == tmpcmd.advertising))
++ return 0;
++ return -EOPNOTSUPP;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/mdio_10g.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/mdio_10g.h
+--- linux-2.6.18.8/drivers/net/sfc/mdio_10g.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/mdio_10g.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,295 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_MDIO_10G_H
++#define EFX_MDIO_10G_H
++
++/*
++ * Definitions needed for doing 10G MDIO as specified in clause 45
++ * MDIO, which do not appear in Linux yet. Also some helper functions.
++ */
++
++#include "efx.h"
++#include "boards.h"
++
++/* Numbering of the MDIO Manageable Devices (MMDs) */
++/* Physical Medium Attachment/ Physical Medium Dependent sublayer */
++#define MDIO_MMD_PMAPMD (1)
++/* WAN Interface Sublayer */
++#define MDIO_MMD_WIS (2)
++/* Physical Coding Sublayer */
++#define MDIO_MMD_PCS (3)
++/* PHY Extender Sublayer */
++#define MDIO_MMD_PHYXS (4)
++/* Extender Sublayer */
++#define MDIO_MMD_DTEXS (5)
++/* Transmission convergence */
++#define MDIO_MMD_TC (6)
++/* Auto negotiation */
++#define MDIO_MMD_AN (7)
++
++/* Generic register locations */
++#define MDIO_MMDREG_CTRL1 (0)
++#define MDIO_MMDREG_STAT1 (1)
++#define MDIO_MMDREG_IDHI (2)
++#define MDIO_MMDREG_IDLOW (3)
++#define MDIO_MMDREG_SPEED (4)
++#define MDIO_MMDREG_DEVS0 (5)
++#define MDIO_MMDREG_DEVS1 (6)
++#define MDIO_MMDREG_CTRL2 (7)
++#define MDIO_MMDREG_STAT2 (8)
++#define MDIO_MMDREG_TXDIS (9)
++
++/* Bits in MMDREG_CTRL1 */
++/* Reset */
++#define MDIO_MMDREG_CTRL1_RESET_LBN (15)
++#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1)
++/* Loopback */
++/* Note that while WIS, PCS, PHYXS and DTEXS have the loopback bit here,
++ * the PMA/PMD does not. */
++#define MDIO_MMDREG_CTRL1_LBACK_LBN (14)
++#define MDIO_MMDREG_CTRL1_LBACK_WIDTH (1)
++/* Low power */
++#define MDIO_MMDREG_CTRL1_LPOWER_LBN (11)
++#define MDIO_MMDREG_CTRL1_LPOWER_WIDTH (1)
++
++/* Bits in MMDREG_STAT1 */
++#define MDIO_MMDREG_STAT1_FAULT_LBN (7)
++#define MDIO_MMDREG_STAT1_FAULT_WIDTH (1)
++/* Link state */
++#define MDIO_MMDREG_STAT1_LINK_LBN (2)
++#define MDIO_MMDREG_STAT1_LINK_WIDTH (1)
++/* Low power ability */
++#define MDIO_MMDREG_STAT1_LPABLE_LBN (1)
++#define MDIO_MMDREG_STAT1_LPABLE_WIDTH (1)
++
++/* Bits in ID reg */
++#define MDIO_ID_REV(_id32) (_id32 & 0xf)
++#define MDIO_ID_MODEL(_id32) ((_id32 >> 4) & 0x3f)
++#define MDIO_ID_OUI(_id32) (_id32 >> 10)
++
++/* Bits in MMDREG_DEVS0. Someone thoughtfully layed things out
++ * so the 'bit present' bit number of an MMD is the number of
++ * that MMD */
++#define DEV_PRESENT_BIT(_b) (1 << _b)
++
++#define MDIO_MMDREG_DEVS0_DTEXS DEV_PRESENT_BIT(MDIO_MMD_DTEXS)
++#define MDIO_MMDREG_DEVS0_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
++#define MDIO_MMDREG_DEVS0_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS)
++#define MDIO_MMDREG_DEVS0_WIS DEV_PRESENT_BIT(MDIO_MMD_WIS)
++#define MDIO_MMDREG_DEVS0_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
++#define MDIO_MMDREG_DEVS0_AN DEV_PRESENT_BIT(MDIO_MMD_AN)
++
++
++/* Bits in MMDREG_STAT2 */
++#define MDIO_MMDREG_STAT2_PRESENT_VAL (2)
++#define MDIO_MMDREG_STAT2_PRESENT_LBN (14)
++#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2)
++
++/* Bits in MMDREG_TXDIS */
++#define MDIO_MMDREG_TXDIS_GLOBAL_LBN (0)
++#define MDIO_MMDREG_TXDIS_GLOBAL_WIDTH (1)
++
++/* MMD-specific bits, ordered by MMD, then register */
++#define MDIO_PMAPMD_CTRL1_LBACK_LBN (0)
++#define MDIO_PMAPMD_CTRL1_LBACK_WIDTH (1)
++
++/* PMA type (4 bits) */
++#define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0)
++#define MDIO_PMAPMD_CTRL2_10G_EW (0x1)
++#define MDIO_PMAPMD_CTRL2_10G_LW (0x2)
++#define MDIO_PMAPMD_CTRL2_10G_SW (0x3)
++#define MDIO_PMAPMD_CTRL2_10G_LX4 (0x4)
++#define MDIO_PMAPMD_CTRL2_10G_ER (0x5)
++#define MDIO_PMAPMD_CTRL2_10G_LR (0x6)
++#define MDIO_PMAPMD_CTRL2_10G_SR (0x7)
++/* Reserved */
++#define MDIO_PMAPMD_CTRL2_10G_BT (0x9)
++/* Reserved */
++/* Reserved */
++#define MDIO_PMAPMD_CTRL2_1G_BT (0xc)
++/* Reserved */
++#define MDIO_PMAPMD_CTRL2_100_BT (0xe)
++#define MDIO_PMAPMD_CTRL2_10_BT (0xf)
++#define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf)
++
++/* PCS 10GBT registers */
++#define MDIO_PCS_10GBT_STATUS (32)
++#define MDIO_PCS_10GBT_STATUS2 (33)
++#define MDIO_PCS_10GBT_STATUS2_BER_LBN (8)
++#define MDIO_PCS_10GBT_STATUS2_BER_WIDTH (6)
++#define MDIO_PCS_10GBT_STATUS2_ERR_LBN (0)
++#define MDIO_PCS_10GBT_STATUS2_ERR_WIDTH (8)
++
++/* PHY XGXS lane state */
++#define MDIO_PHYXS_LANE_STATE (0x18)
++#define MDIO_PHYXS_LANE_ALIGNED_LBN (12)
++#define MDIO_PHYXS_LANE_SYNC0_LBN (0)
++#define MDIO_PHYXS_LANE_SYNC1_LBN (1)
++#define MDIO_PHYXS_LANE_SYNC2_LBN (2)
++#define MDIO_PHYXS_LANE_SYNC3_LBN (3)
++
++/* AN registers */
++#define MDIO_AN_STATUS (1)
++#define MDIO_AN_STATUS_XNP_LBN (7)
++#define MDIO_AN_STATUS_PAGE_LBN (6)
++#define MDIO_AN_STATUS_AN_DONE_LBN (5)
++#define MDIO_AN_STATUS_LP_AN_CAP_LBN (0)
++
++#define MDIO_AN_10GBT_STATUS (33)
++#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */
++#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */
++#define MDIO_AN_10GBT_STATUS_LOC_OK_LBN (13) /* Local OK */
++#define MDIO_AN_10GBT_STATUS_REM_OK_LBN (12) /* Remote OK */
++#define MDIO_AN_10GBT_STATUS_LP_10G_LBN (11) /* Link partner is 10GBT capable */
++#define MDIO_AN_10GBT_STATUS_LP_LTA_LBN (10) /* LP loop timing ability */
++#define MDIO_AN_10GBT_STATUS_LP_TRR_LBN (9) /* LP Training Reset Request */
++
++
++/* Packing of the prt and dev arguments of clause 45 style MDIO into a
++ * single int so they can be passed into the mdio_read/write functions
++ * that currently exist. Note that as Falcon is the only current user,
++ * the packed form is chosen to match what Falcon needs to write into
++ * a register. This is checked at compile-time so do not change it. If
++ * your target chip needs things layed out differently you will need
++ * to unpack the arguments in your chip-specific mdio functions.
++ */
++ /* These are defined by the standard. */
++#define MDIO45_PRT_ID_WIDTH (5)
++#define MDIO45_DEV_ID_WIDTH (5)
++
++/* The prt ID is just packed in immediately to the left of the dev ID */
++#define MDIO45_PRT_DEV_WIDTH (MDIO45_PRT_ID_WIDTH + MDIO45_DEV_ID_WIDTH)
++
++#define MDIO45_PRT_ID_MASK ((1 << MDIO45_PRT_DEV_WIDTH) - 1)
++/* This is the prt + dev extended by 1 bit to hold the 'is clause 45' flag. */
++#define MDIO45_XPRT_ID_WIDTH (MDIO45_PRT_DEV_WIDTH + 1)
++#define MDIO45_XPRT_ID_MASK ((1 << MDIO45_XPRT_ID_WIDTH) - 1)
++#define MDIO45_XPRT_ID_IS10G (1 << (MDIO45_XPRT_ID_WIDTH - 1))
++
++
++#define MDIO45_PRT_ID_COMP_LBN MDIO45_DEV_ID_WIDTH
++#define MDIO45_PRT_ID_COMP_WIDTH MDIO45_PRT_ID_WIDTH
++#define MDIO45_DEV_ID_COMP_LBN 0
++#define MDIO45_DEV_ID_COMP_WIDTH MDIO45_DEV_ID_WIDTH
++
++/* Compose port and device into a phy_id */
++static inline int mdio_clause45_pack(u8 prt, u8 dev)
++{
++ efx_dword_t phy_id;
++ EFX_POPULATE_DWORD_2(phy_id, MDIO45_PRT_ID_COMP, prt,
++ MDIO45_DEV_ID_COMP, dev);
++ return MDIO45_XPRT_ID_IS10G | EFX_DWORD_VAL(phy_id);
++}
++
++static inline void mdio_clause45_unpack(u32 val, u8 *prt, u8 *dev)
++{
++ efx_dword_t phy_id;
++ EFX_POPULATE_DWORD_1(phy_id, EFX_DWORD_0, val);
++ *prt = EFX_DWORD_FIELD(phy_id, MDIO45_PRT_ID_COMP);
++ *dev = EFX_DWORD_FIELD(phy_id, MDIO45_DEV_ID_COMP);
++}
++
++static inline int mdio_clause45_read(struct efx_nic *efx,
++ u8 prt, u8 dev, u16 addr)
++{
++ return efx->mii.mdio_read(efx->net_dev,
++ mdio_clause45_pack(prt, dev), addr);
++}
++
++static inline void mdio_clause45_write(struct efx_nic *efx,
++ u8 prt, u8 dev, u16 addr, int value)
++{
++ efx->mii.mdio_write(efx->net_dev,
++ mdio_clause45_pack(prt, dev), addr, value);
++}
++
++
++static inline u32 mdio_clause45_read_id(struct efx_nic *efx, int mmd)
++{
++ int phy_id = efx->mii.phy_id;
++ u16 id_low = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDLOW);
++ u16 id_hi = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDHI);
++ return (id_hi << 16) | (id_low);
++}
++
++static inline int mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx)
++{
++ int i, sync, lane_status;
++
++ for (i = 0; i < 2; ++i)
++ lane_status = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS,
++ MDIO_PHYXS_LANE_STATE);
++
++ sync = (lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN)) != 0;
++ if (!sync)
++ EFX_INFO(efx, "XGXS lane status: %x\n", lane_status);
++ return sync;
++}
++
++extern const char *mdio_clause45_mmd_name(int mmd);
++
++/*
++ * Reset a specific MMD and wait for reset to clear.
++ * Return number of spins left (>0) on success, -%ETIMEDOUT on failure.
++ *
++ * This function will sleep
++ */
++extern int mdio_clause45_reset_mmd(struct efx_nic *efx, int mmd,
++ int spins, int spintime);
++
++/* As mdio_clause45_check_mmd but for multiple MMDs */
++int mdio_clause45_check_mmds(struct efx_nic *efx,
++ unsigned int mmd_mask, unsigned int fatal_mask);
++
++/* Check the link status of specified mmds in bit mask */
++extern int mdio_clause45_links_ok(struct efx_nic *efx,
++ unsigned int mmd_mask);
++
++/* Generic transmit disable support though PMAPMD */
++extern void mdio_clause45_transmit_disable(struct efx_nic *efx,
++ int disable);
++
++/* Generic part of reconfigure: set/clear loopback bits */
++extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx);
++
++/* Set the power state of the specified MMDs */
++extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
++ int low_power, unsigned int mmd_mask);
++
++/* Read (some of) the PHY settings over MDIO */
++extern void mdio_clause45_get_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd);
++
++/* Set (some of) the PHY settings over MDIO */
++extern int mdio_clause45_set_settings(struct efx_nic *efx,
++ struct ethtool_cmd *ecmd);
++
++/* Wait for specified MMDs to exit reset within a timeout */
++extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
++ unsigned int mmd_mask);
++
++#endif /* EFX_MDIO_10G_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/mentormac.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/mentormac.c
+--- linux-2.6.18.8/drivers/net/sfc/mentormac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/mentormac.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,506 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/delay.h>
++#include "net_driver.h"
++#include "gmii.h"
++#include "mac.h"
++
++/*
++ * Mentor MAC control
++ */
++
++/**************************************************************************
++ *
++ * Mentor MAC registers
++ *
++ **************************************************************************
++ *
++ * Register addresses are Mentor MAC register numbers. Falcon maps these
++ * registers in at 16-byte intervals. The mac_writel() and mac_readl()
++ * methods take care of abstracting away this difference.
++ */
++
++/* GMAC configuration register 1 */
++#define GM_CFG1_REG_MAC 0x00
++#define GM_SW_RST_LBN 31
++#define GM_SW_RST_WIDTH 1
++#define GM_SIM_RST_LBN 30
++#define GM_SIM_RST_WIDTH 1
++#define GM_RST_RX_MAC_CTL_LBN 19
++#define GM_RST_RX_MAC_CTL_WIDTH 1
++#define GM_RST_TX_MAC_CTL_LBN 18
++#define GM_RST_TX_MAC_CTL_WIDTH 1
++#define GM_RST_RX_FUNC_LBN 17
++#define GM_RST_RX_FUNC_WIDTH 1
++#define GM_RST_TX_FUNC_LBN 16
++#define GM_RST_TX_FUNC_WIDTH 1
++#define GM_LOOP_LBN 8
++#define GM_LOOP_WIDTH 1
++#define GM_RX_FC_EN_LBN 5
++#define GM_RX_FC_EN_WIDTH 1
++#define GM_TX_FC_EN_LBN 4
++#define GM_TX_FC_EN_WIDTH 1
++#define GM_SYNC_RXEN_LBN 3
++#define GM_SYNC_RXEN_WIDTH 1
++#define GM_RX_EN_LBN 2
++#define GM_RX_EN_WIDTH 1
++#define GM_SYNC_TXEN_LBN 1
++#define GM_SYNC_TXEN_WIDTH 1
++#define GM_TX_EN_LBN 0
++#define GM_TX_EN_WIDTH 1
++
++/* GMAC configuration register 2 */
++#define GM_CFG2_REG_MAC 0x01
++#define GM_PAMBL_LEN_LBN 12
++#define GM_PAMBL_LEN_WIDTH 4
++#define GM_IF_MODE_LBN 8
++#define GM_IF_MODE_WIDTH 2
++#define GM_HUGE_FRM_EN_LBN 5
++#define GM_HUGE_FRM_EN_WIDTH 1
++#define GM_LEN_CHK_LBN 4
++#define GM_LEN_CHK_WIDTH 1
++#define GM_PAD_CRC_EN_LBN 2
++#define GM_PAD_CRC_EN_WIDTH 1
++#define GM_CRC_EN_LBN 1
++#define GM_CRC_EN_WIDTH 1
++#define GM_FD_LBN 0
++#define GM_FD_WIDTH 1
++
++/* GMAC maximum frame length register */
++#define GM_MAX_FLEN_REG_MAC 0x04
++#define GM_MAX_FLEN_LBN 0
++#define GM_MAX_FLEN_WIDTH 16
++
++/* GMAC MII management configuration register */
++#define GM_MII_MGMT_CFG_REG_MAC 0x08
++#define GM_RST_MII_MGMT_LBN 31
++#define GM_RST_MII_MGMT_WIDTH 1
++#define GM_MGMT_SCAN_AUTO_INC_LBN 5
++#define GM_MGMT_SCAN_AUTO_INC_WIDTH 1
++#define GM_MGMT_PREM_SUPR_LBN 4
++#define GM_MGMT_PREM_SUPR_WIDTH 1
++#define GM_MGMT_CLK_SEL_LBN 0
++#define GM_MGMT_CLK_SEL_WIDTH 3
++
++/* GMAC MII management command register */
++#define GM_MII_MGMT_CMD_REG_MAC 0x09
++#define GM_MGMT_SCAN_CYC_LBN 1
++#define GM_MGMT_SCAN_CYC_WIDTH 1
++#define GM_MGMT_RD_CYC_LBN 0
++#define GM_MGMT_RD_CYC_WIDTH 1
++
++/* GMAC MII management address register */
++#define GM_MII_MGMT_ADR_REG_MAC 0x0a
++#define GM_MGMT_PHY_ADDR_LBN 8
++#define GM_MGMT_PHY_ADDR_WIDTH 5
++#define GM_MGMT_REG_ADDR_LBN 0
++#define GM_MGMT_REG_ADDR_WIDTH 5
++
++/* GMAC MII management control register */
++#define GM_MII_MGMT_CTL_REG_MAC 0x0b
++#define GM_MGMT_CTL_LBN 0
++#define GM_MGMT_CTL_WIDTH 16
++
++/* GMAC MII management status register */
++#define GM_MII_MGMT_STAT_REG_MAC 0x0c
++#define GM_MGMT_STAT_LBN 0
++#define GM_MGMT_STAT_WIDTH 16
++
++/* GMAC MII management indicators register */
++#define GM_MII_MGMT_IND_REG_MAC 0x0d
++#define GM_MGMT_NOT_VLD_LBN 2
++#define GM_MGMT_NOT_VLD_WIDTH 1
++#define GM_MGMT_SCANNING_LBN 1
++#define GM_MGMT_SCANNING_WIDTH 1
++#define GM_MGMT_BUSY_LBN 0
++#define GM_MGMT_BUSY_WIDTH 1
++
++/* GMAC station address register 1 */
++#define GM_ADR1_REG_MAC 0x10
++#define GM_HWADDR_5_LBN 24
++#define GM_HWADDR_5_WIDTH 8
++#define GM_HWADDR_4_LBN 16
++#define GM_HWADDR_4_WIDTH 8
++#define GM_HWADDR_3_LBN 8
++#define GM_HWADDR_3_WIDTH 8
++#define GM_HWADDR_2_LBN 0
++#define GM_HWADDR_2_WIDTH 8
++
++/* GMAC station address register 2 */
++#define GM_ADR2_REG_MAC 0x11
++#define GM_HWADDR_1_LBN 24
++#define GM_HWADDR_1_WIDTH 8
++#define GM_HWADDR_0_LBN 16
++#define GM_HWADDR_0_WIDTH 8
++
++/* GMAC FIFO configuration register 0 */
++#define GMF_CFG0_REG_MAC 0x12
++#define GMF_FTFENRPLY_LBN 20
++#define GMF_FTFENRPLY_WIDTH 1
++#define GMF_STFENRPLY_LBN 19
++#define GMF_STFENRPLY_WIDTH 1
++#define GMF_FRFENRPLY_LBN 18
++#define GMF_FRFENRPLY_WIDTH 1
++#define GMF_SRFENRPLY_LBN 17
++#define GMF_SRFENRPLY_WIDTH 1
++#define GMF_WTMENRPLY_LBN 16
++#define GMF_WTMENRPLY_WIDTH 1
++#define GMF_FTFENREQ_LBN 12
++#define GMF_FTFENREQ_WIDTH 1
++#define GMF_STFENREQ_LBN 11
++#define GMF_STFENREQ_WIDTH 1
++#define GMF_FRFENREQ_LBN 10
++#define GMF_FRFENREQ_WIDTH 1
++#define GMF_SRFENREQ_LBN 9
++#define GMF_SRFENREQ_WIDTH 1
++#define GMF_WTMENREQ_LBN 8
++#define GMF_WTMENREQ_WIDTH 1
++#define GMF_HSTRSTFT_LBN 4
++#define GMF_HSTRSTFT_WIDTH 1
++#define GMF_HSTRSTST_LBN 3
++#define GMF_HSTRSTST_WIDTH 1
++#define GMF_HSTRSTFR_LBN 2
++#define GMF_HSTRSTFR_WIDTH 1
++#define GMF_HSTRSTSR_LBN 1
++#define GMF_HSTRSTSR_WIDTH 1
++#define GMF_HSTRSTWT_LBN 0
++#define GMF_HSTRSTWT_WIDTH 1
++
++/* GMAC FIFO configuration register 1 */
++#define GMF_CFG1_REG_MAC 0x13
++#define GMF_CFGFRTH_LBN 16
++#define GMF_CFGFRTH_WIDTH 5
++#define GMF_CFGXOFFRTX_LBN 0
++#define GMF_CFGXOFFRTX_WIDTH 16
++
++/* GMAC FIFO configuration register 2 */
++#define GMF_CFG2_REG_MAC 0x14
++#define GMF_CFGHWM_LBN 16
++#define GMF_CFGHWM_WIDTH 6
++#define GMF_CFGLWM_LBN 0
++#define GMF_CFGLWM_WIDTH 6
++
++/* GMAC FIFO configuration register 3 */
++#define GMF_CFG3_REG_MAC 0x15
++#define GMF_CFGHWMFT_LBN 16
++#define GMF_CFGHWMFT_WIDTH 6
++#define GMF_CFGFTTH_LBN 0
++#define GMF_CFGFTTH_WIDTH 6
++
++/* GMAC FIFO configuration register 4 */
++#define GMF_CFG4_REG_MAC 0x16
++#define GMF_HSTFLTRFRM_LBN 0
++#define GMF_HSTFLTRFRM_WIDTH 18
++#define GMF_HSTFLTRFRM_PAUSE_LBN 12
++#define GMF_HSTFLTRFRM_PAUSE_WIDTH 12
++
++/* GMAC FIFO configuration register 5 */
++#define GMF_CFG5_REG_MAC 0x17
++#define GMF_CFGHDPLX_LBN 22
++#define GMF_CFGHDPLX_WIDTH 1
++#define GMF_SRFULL_LBN 21
++#define GMF_SRFULL_WIDTH 1
++#define GMF_HSTSRFULLCLR_LBN 20
++#define GMF_HSTSRFULLCLR_WIDTH 1
++#define GMF_CFGBYTMODE_LBN 19
++#define GMF_CFGBYTMODE_WIDTH 1
++#define GMF_HSTDRPLT64_LBN 18
++#define GMF_HSTDRPLT64_WIDTH 1
++#define GMF_HSTFLTRFRMDC_LBN 0
++#define GMF_HSTFLTRFRMDC_WIDTH 18
++#define GMF_HSTFLTRFRMDC_PAUSE_LBN 12
++#define GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1
++
++/* TX total octet count */
++#define GM_TX_OCT_CNT_REG_MAC 0x40
++#define GM_STAT_LBN 0
++#define GM_STAT_WIDTH 32
++
++/* TX good octet count */
++#define GM_TX_GOOD_OCT_CNT_REG_MAC 0x41
++
++/* TX single collision packet count */
++#define GM_TX_SGLCOL_PKT_CNT_REG_MAC 0x42
++
++/* TX multiple collision packet count */
++#define GM_TX_MULTCOL_PKT_CNT_REG_MAC 0x43
++
++/* TX excessive collision packet count */
++#define GM_TX_EXCOL_PKT_CNT_REG_MAC 0x44
++
++/* TX deferred packet count */
++#define GM_TX_DEF_PKT_CNT_REG_MAC 0x45
++
++/* TX late packet count */
++#define GM_TX_LATECOL_PKT_CNT_REG_MAC 0x46
++
++/* TX excessive deferral packet count */
++#define GM_TX_EXDEF_PKT_CNT_REG_MAC 0x47
++
++/* TX pause packet count */
++#define GM_TX_PAUSE_PKT_CNT_REG_MAC 0x48
++
++/* TX bad packet count */
++#define GM_TX_BAD_PKT_CNT_REG_MAC 0x49
++
++/* TX unicast packet count */
++#define GM_TX_UCAST_PKT_CNT_REG_MAC 0x4a
++
++/* TX multicast packet count */
++#define GM_TX_MCAST_PKT_CNT_REG_MAC 0x4b
++
++/* TX broadcast packet count */
++#define GM_TX_BCAST_PKT_CNT_REG_MAC 0x4c
++
++/* TX <64-byte packet count */
++#define GM_TX_LT64_PKT_CNT_REG_MAC 0x4d
++
++/* TX 64-byte packet count */
++#define GM_TX_64_PKT_CNT_REG_MAC 0x4e
++
++/* TX 65-byte to 127-byte packet count */
++#define GM_TX_65_TO_127_PKT_CNT_REG_MAC 0x4f
++
++/* TX 128-byte to 255-byte packet count */
++#define GM_TX_128_TO_255_PKT_CNT_REG_MAC 0x50
++
++/* TX 256-byte to 511-byte packet count */
++#define GM_TX_256_TO_511_PKT_CNT_REG_MAC 0x51
++
++/* TX 512-byte to 1023-byte packet count */
++#define GM_TX_512_TO_1023_PKT_CNT_REG_MAC 0x52
++
++/* TX 1024-byte to 15xx-byte packet count */
++#define GM_TX_1024_TO_15XX_PKT_CNT_REG_MAC 0x53
++
++/* TX 15xx-byte to jumbo packet count */
++#define GM_TX_15XX_TO_JUMBO_PKT_CNT_REG_MAC 0x54
++
++/* TX >jumbo packet count */
++#define GM_TX_GTJUMBO_PKT_CNT_REG_MAC 0x55
++
++/* RX good octet count */
++#define GM_RX_GOOD_OCT_CNT_REG_MAC 0x60
++
++/* RX bad octet count */
++#define GM_RX_BAD_OCT_CNT_REG_MAC 0x61
++
++/* RX missed packet count */
++#define GM_RX_MISS_PKT_CNT_REG_MAC 0x62
++
++/* RX false carrier count */
++#define GM_RX_FALSE_CRS_CNT_REG_MAC 0x63
++
++/* RX pause packet count */
++#define GM_RX_PAUSE_PKT_CNT_REG_MAC 0x64
++
++/* RX bad packet count */
++#define GM_RX_BAD_PKT_CNT_REG_MAC 0x65
++
++/* RX unicast packet count */
++#define GM_RX_UCAST_PKT_CNT_REG_MAC 0x66
++
++/* RX multicast packet count */
++#define GM_RX_MCAST_PKT_CNT_REG_MAC 0x67
++
++/* RX broadcast packet count */
++#define GM_RX_BCAST_PKT_CNT_REG_MAC 0x68
++
++/* RX <64-byte good packet count */
++#define GM_RX_GOOD_LT64_PKT_CNT_REG_MAC 0x69
++
++/* RX <64-byte bad packet count */
++#define GM_RX_BAD_LT64_PKT_CNT_REG_MAC 0x6a
++
++/* RX 64-byte packet count */
++#define GM_RX_64_PKT_CNT_REG_MAC 0x6b
++
++/* RX 65-byte to 127-byte packet count */
++#define GM_RX_65_TO_127_PKT_CNT_REG_MAC 0x6c
++
++/* RX 128-byte to 255-byte packet count*/
++#define GM_RX_128_TO_255_PKT_CNT_REG_MAC 0x6d
++
++/* RX 256-byte to 511-byte packet count */
++#define GM_RX_256_TO_511_PKT_CNT_REG_MAC 0x6e
++
++/* RX 512-byte to 1023-byte packet count */
++#define GM_RX_512_TO_1023_PKT_CNT_REG_MAC 0x6f
++
++/* RX 1024-byte to 15xx-byte packet count */
++#define GM_RX_1024_TO_15XX_PKT_CNT_REG_MAC 0x70
++
++/* RX 15xx-byte to jumbo packet count */
++#define GM_RX_15XX_TO_JUMBO_PKT_CNT_REG_MAC 0x71
++
++/* RX >jumbo packet count */
++#define GM_RX_GTJUMBO_PKT_CNT_REG_MAC 0x72
++
++/* RX 64-byte to 15xx-byte bad crc packet count */
++#define GM_RX_BAD_64_TO_15XX_PKT_CNT_REG_MAC 0x73
++
++/* RX 15xx-byte to jumbo bad crc packet count */
++#define GM_RX_BAD_15XX_TO_JUMBO_PKT_CNT_REG_MAC 0x74
++
++/* RX >jumbo bad crc packet count */
++#define GM_RX_BAD_GTJUMBO_PKT_CNT_REG_MAC 0x75
++
++/**************************************************************************
++ *
++ * GMII access to PHY
++ *
++ **************************************************************************
++ */
++
++/* This does not reset the PHY, only the MAC. However, TX and RX will
++ * both be disabled on the MAC after this, so the state of the PHY is
++ * somewhat irrelevant until the MAC is reinitialised.
++ */
++void mentormac_reset(struct efx_nic *efx)
++{
++ efx_dword_t reg;
++
++ EFX_POPULATE_DWORD_1(reg, GM_SW_RST, 1);
++ efx->mac_op->mac_writel(efx, &reg, GM_CFG1_REG_MAC);
++ udelay(1000);
++
++ EFX_POPULATE_DWORD_1(reg, GM_SW_RST, 0);
++ efx->mac_op->mac_writel(efx, &reg, GM_CFG1_REG_MAC);
++ udelay(1000);
++
++ /* Configure GMII interface so PHY is accessible */
++ EFX_POPULATE_DWORD_1(reg, GM_MGMT_CLK_SEL, 0x4);
++ efx->mac_op->mac_writel(efx, &reg,
++ GM_MII_MGMT_CFG_REG_MAC);
++ udelay(10);
++}
++
++void mentormac_reconfigure(struct efx_nic *efx)
++{
++ int loopback, tx_fc, rx_fc, if_mode, full_duplex, bytemode, half_duplex;
++ unsigned int max_frame_len;
++ efx_dword_t reg;
++
++ /* Configuration register 1 */
++ tx_fc = (efx->flow_control & EFX_FC_TX) ? 1 : 0;
++ rx_fc = (efx->flow_control & EFX_FC_RX) ? 1 : 0;
++ loopback = (efx->loopback_mode == LOOPBACK_MAC) ? 1 : 0;
++ bytemode = (efx->link_options & GM_LPA_1000) ? 1 : 0;
++
++ if (efx->loopback_mode != LOOPBACK_NONE)
++ bytemode = 1;
++ if (!(efx->link_options & GM_LPA_DUPLEX))
++ /* Half-duplex operation requires TX flow control */
++ tx_fc = 1;
++ EFX_POPULATE_DWORD_5(reg,
++ GM_LOOP, loopback,
++ GM_TX_EN, 1,
++ GM_TX_FC_EN, tx_fc,
++ GM_RX_EN, 1,
++ GM_RX_FC_EN, rx_fc);
++ efx->mac_op->mac_writel(efx, &reg, GM_CFG1_REG_MAC);
++ udelay(10);
++
++ /* Configuration register 2 */
++ if_mode = (bytemode) ? 2 : 1;
++ full_duplex = (efx->link_options & GM_LPA_DUPLEX) ? 1 : 0;
++ EFX_POPULATE_DWORD_4(reg,
++ GM_IF_MODE, if_mode,
++ GM_PAD_CRC_EN, 1,
++ GM_FD, full_duplex,
++ GM_PAMBL_LEN, 0x7/*datasheet recommended */);
++
++ efx->mac_op->mac_writel(efx, &reg, GM_CFG2_REG_MAC);
++ udelay(10);
++
++ /* Max frame len register */
++ max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
++ EFX_POPULATE_DWORD_1(reg, GM_MAX_FLEN, max_frame_len);
++ efx->mac_op->mac_writel(efx, &reg, GM_MAX_FLEN_REG_MAC);
++ udelay(10);
++
++ /* FIFO configuration register 0 */
++ EFX_POPULATE_DWORD_5(reg,
++ GMF_FTFENREQ, 1,
++ GMF_STFENREQ, 1,
++ GMF_FRFENREQ, 1,
++ GMF_SRFENREQ, 1,
++ GMF_WTMENREQ, 1);
++ efx->mac_op->mac_writel(efx, &reg, GMF_CFG0_REG_MAC);
++ udelay(10);
++
++ /* FIFO configuration register 1 */
++ EFX_POPULATE_DWORD_2(reg,
++ GMF_CFGFRTH, 0x12,
++ GMF_CFGXOFFRTX, 0xffff);
++ efx->mac_op->mac_writel(efx, &reg, GMF_CFG1_REG_MAC);
++ udelay(10);
++
++ /* FIFO configuration register 2 */
++ EFX_POPULATE_DWORD_2(reg,
++ GMF_CFGHWM, 0x3f,
++ GMF_CFGLWM, 0xa);
++ efx->mac_op->mac_writel(efx, &reg, GMF_CFG2_REG_MAC);
++ udelay(10);
++
++ /* FIFO configuration register 3 */
++ EFX_POPULATE_DWORD_2(reg,
++ GMF_CFGHWMFT, 0x1c,
++ GMF_CFGFTTH, 0x08);
++ efx->mac_op->mac_writel(efx, &reg, GMF_CFG3_REG_MAC);
++ udelay(10);
++
++ /* FIFO configuration register 4 */
++ EFX_POPULATE_DWORD_1(reg, GMF_HSTFLTRFRM_PAUSE, 1);
++ efx->mac_op->mac_writel(efx, &reg, GMF_CFG4_REG_MAC);
++ udelay(10);
++
++ /* FIFO configuration register 5 */
++ half_duplex = (efx->link_options & GM_LPA_DUPLEX) ? 0 : 1;
++ efx->mac_op->mac_readl(efx, &reg, GMF_CFG5_REG_MAC);
++ EFX_SET_DWORD_FIELD(reg, GMF_CFGBYTMODE, bytemode);
++ EFX_SET_DWORD_FIELD(reg, GMF_CFGHDPLX, half_duplex);
++ EFX_SET_DWORD_FIELD(reg, GMF_HSTDRPLT64, half_duplex);
++ EFX_SET_DWORD_FIELD(reg, GMF_HSTFLTRFRMDC_PAUSE, 0);
++ efx->mac_op->mac_writel(efx, &reg, GMF_CFG5_REG_MAC);
++ udelay(10);
++
++ /* MAC address */
++ EFX_POPULATE_DWORD_4(reg,
++ GM_HWADDR_5, efx->net_dev->dev_addr[5],
++ GM_HWADDR_4, efx->net_dev->dev_addr[4],
++ GM_HWADDR_3, efx->net_dev->dev_addr[3],
++ GM_HWADDR_2, efx->net_dev->dev_addr[2]);
++ efx->mac_op->mac_writel(efx, &reg, GM_ADR1_REG_MAC);
++ udelay(10);
++ EFX_POPULATE_DWORD_2(reg,
++ GM_HWADDR_1, efx->net_dev->dev_addr[1],
++ GM_HWADDR_0, efx->net_dev->dev_addr[0]);
++ efx->mac_op->mac_writel(efx, &reg, GM_ADR2_REG_MAC);
++ udelay(10);
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/mtd.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/mtd.c
+--- linux-2.6.18.8/drivers/net/sfc/mtd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/mtd.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,602 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/delay.h>
++
++#define EFX_DRIVER_NAME "sfc_mtd"
++#include "driverlink_api.h"
++#include "net_driver.h"
++#include "spi.h"
++
++/*
++ * Flash and EEPROM (MTD) device driver
++ *
++ * This file provides a separate kernel module (sfc_mtd) which
++ * exposes the flash and EEPROM devices present on Solarflare NICs as
++ * MTD devices, enabling you to reflash the boot ROM code (or use the
++ * remaining space on the flash as a jffs2 filesystem, should you want
++ * to do so).
++ */
++
++#define EFX_MTD_VERIFY_BUF_LEN 16
++#define EFX_MAX_PARTITIONS 2
++#define EFX_FLASH_BOOTROM_OFFSET 0x8000U
++
++/* Write enable for EEPROM/flash configuration area
++ *
++ * Normally, writes to parts of non-volatile storage which contain
++ * critical configuration are disabled to prevent accidents. This
++ * parameter allows enabling of such writes.
++ */
++static unsigned int efx_allow_nvconfig_writes;
++
++struct efx_mtd {
++ struct mtd_info mtd;
++ struct mtd_partition part[EFX_MAX_PARTITIONS];
++ char part_name[EFX_MAX_PARTITIONS][32];
++ char name[32];
++ struct efx_dl_device *efx_dev;
++ struct efx_nic *efx;
++ /* This must be held when using *spi; it guards against races
++ * with device reset and between sequences of dependent
++ * commands. */
++ struct semaphore access_lock;
++ struct efx_spi_device *spi;
++};
++
++/* SPI utilities */
++
++static int efx_spi_fast_wait(struct efx_mtd *efx_mtd)
++{
++ struct efx_spi_device *spi = efx_mtd->spi;
++ u8 status;
++ int i, rc;
++
++ /* Wait up to 1000us for flash/EEPROM to finish a fast operation. */
++ for (i = 0; i < 50; i++) {
++ udelay(20);
++
++ rc = spi->read(spi, efx_mtd->efx, SPI_RDSR, -1,
++ &status, sizeof(status));
++ if (rc)
++ return rc;
++ if (!(status & SPI_STATUS_NRDY))
++ return 0;
++ }
++ EFX_ERR(efx_mtd->efx, "timed out waiting for %s last status=0x%02x\n",
++ efx_mtd->name, status);
++ return -ETIMEDOUT;
++}
++
++static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, int uninterruptible)
++{
++ struct efx_spi_device *spi = efx_mtd->spi;
++ u8 status;
++ int rc, i;
++
++ /* Wait up to 4s for flash/EEPROM to finish a slow operation. */
++ for (i = 0; i < 40; i++) {
++ __set_current_state(uninterruptible ?
++ TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
++ schedule_timeout(HZ / 10);
++ rc = spi->read(spi, efx_mtd->efx, SPI_RDSR, -1,
++ &status, sizeof(status));
++ if (rc)
++ return rc;
++ if (!(status & SPI_STATUS_NRDY))
++ return 0;
++ if (signal_pending(current))
++ return -EINTR;
++ }
++ EFX_ERR(efx_mtd->efx, "timed out waiting for %s\n", efx_mtd->name);
++ return -ETIMEDOUT;
++}
++
++static int
++efx_spi_write_enable(struct efx_mtd *efx_mtd)
++{
++ struct efx_spi_device *spi = efx_mtd->spi;
++
++ return spi->write(spi, efx_mtd->efx, SPI_WREN, -1, NULL, 0);
++}
++
++static int efx_spi_unlock(struct efx_mtd *efx_mtd)
++{
++ struct efx_spi_device *spi = efx_mtd->spi;
++ const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 |
++ SPI_STATUS_BP0);
++ u8 status;
++ int rc;
++
++ rc = spi->read(spi, efx_mtd->efx, SPI_RDSR, -1, &status,
++ sizeof(status));
++ if (rc)
++ return rc;
++
++ if (!(status & unlock_mask))
++ return 0; /* already unlocked */
++
++ rc = efx_spi_write_enable(efx_mtd);
++ if (rc)
++ return rc;
++ rc = spi->write(spi, efx_mtd->efx, SPI_SST_EWSR, -1, NULL, 0);
++ if (rc)
++ return rc;
++
++ status &= ~unlock_mask;
++ rc = spi->write(spi, efx_mtd->efx, SPI_WRSR, -1, &status,
++ sizeof(status));
++ if (rc)
++ return rc;
++ rc = efx_spi_fast_wait(efx_mtd);
++ if (rc)
++ return rc;
++
++ return 0;
++}
++
++/* Dummy device used in case of a failed reset */
++
++static int efx_spi_dummy_read(const struct efx_spi_device *spi,
++ struct efx_nic *efx, unsigned int command,
++ int address, void *data, unsigned int len)
++{
++ return -EIO;
++}
++
++static int efx_spi_dummy_write(const struct efx_spi_device *spi,
++ struct efx_nic *efx, unsigned int command,
++ int address, const void *data, unsigned int len)
++{
++ return -EIO;
++}
++
++static struct efx_spi_device efx_spi_dummy_device = {
++ .block_size = 1,
++ .erase_command = 0xff,
++ .read = efx_spi_dummy_read,
++ .write = efx_spi_dummy_write,
++};
++
++/* MTD interface */
++
++static int efx_mtd_read(struct mtd_info *mtd, loff_t start, size_t len,
++ size_t *retlen, u8 *buffer)
++{
++ struct efx_mtd *efx_mtd = mtd->priv;
++ struct efx_spi_device *spi;
++ unsigned int command;
++ unsigned int block_len;
++ unsigned int pos = 0;
++ int rc;
++
++ rc = down_interruptible(&efx_mtd->access_lock);
++ if (rc)
++ goto out;
++ spi = efx_mtd->spi;
++
++ while (pos < len) {
++ block_len = min((unsigned int)len - pos,
++ efx_spi_read_limit(spi, start + pos));
++ command = efx_spi_munge_command(spi, SPI_READ, start + pos);
++ rc = spi->read(spi, efx_mtd->efx, command, start + pos,
++ buffer + pos, block_len);
++ if (rc)
++ break;
++ pos += block_len;
++
++ /* Avoid locking up the system */
++ cond_resched();
++ if (signal_pending(current)) {
++ rc = -EINTR;
++ break;
++ }
++ }
++
++ up(&efx_mtd->access_lock);
++out:
++ *retlen = pos;
++ return rc;
++}
++
++/* Check that device contents match buffer. If repeat is true, buffer
++ * contains a pattern of length EFX_MTD_VERIFY_BUF_LEN which the
++ * device contents should match repeatedly.
++ */
++static int efx_mtd_verify(struct mtd_info *mtd, loff_t start,
++ size_t len, const u8 *buffer, int repeat)
++{
++ u8 verify_buffer[EFX_MTD_VERIFY_BUF_LEN];
++ unsigned int block_len;
++ size_t read_len;
++ unsigned int pos = 0;
++ int rc = 0;
++
++ while (pos < len) {
++ block_len = min(len - pos, sizeof(verify_buffer));
++ rc = efx_mtd_read(mtd, start + pos, block_len, &read_len,
++ verify_buffer);
++ if (rc)
++ return rc;
++ if (memcmp(repeat ? buffer : buffer + pos, verify_buffer,
++ block_len))
++ return -EIO;
++ pos += block_len;
++ }
++
++ return 0;
++}
++
++static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
++{
++ struct efx_mtd *efx_mtd = mtd->priv;
++ struct efx_spi_device *spi;
++ u8 empty[EFX_MTD_VERIFY_BUF_LEN];
++ int rc;
++
++ if (erase->len != mtd->erasesize) {
++ rc = -EINVAL;
++ goto out;
++ }
++
++ rc = down_interruptible(&efx_mtd->access_lock);
++ if (rc)
++ goto out;
++ spi = efx_mtd->spi;
++ if (spi->erase_command == 0) {
++ rc = -EOPNOTSUPP;
++ goto out_up;
++ }
++
++ rc = efx_spi_unlock(efx_mtd);
++ if (rc)
++ goto out_up;
++ rc = efx_spi_write_enable(efx_mtd);
++ if (rc)
++ goto out_up;
++ rc = spi->write(spi, efx_mtd->efx, spi->erase_command, erase->addr,
++ NULL, 0);
++ if (rc)
++ goto out_up;
++ rc = efx_spi_slow_wait(efx_mtd, 0);
++
++out_up:
++ up(&efx_mtd->access_lock);
++ if (rc)
++ goto out;
++
++ memset(empty, 0xff, sizeof(empty));
++ rc = efx_mtd_verify(mtd, erase->addr, erase->len, empty, 1);
++
++out:
++ if (rc == 0) {
++ erase->state = MTD_ERASE_DONE;
++ } else {
++ erase->state = MTD_ERASE_FAILED;
++#if defined(EFX_USE_MTD_ERASE_FAIL_ADDR)
++ erase->fail_addr = 0xffffffff;
++#endif
++ }
++ mtd_erase_callback(erase);
++ return rc;
++}
++
++static int efx_mtd_write(struct mtd_info *mtd, loff_t start,
++ size_t len, size_t *retlen, const u8 *buffer)
++{
++ struct efx_mtd *efx_mtd = mtd->priv;
++ struct efx_spi_device *spi;
++ unsigned int command;
++ unsigned int block_len;
++ unsigned int pos = 0;
++ int rc;
++
++ rc = down_interruptible(&efx_mtd->access_lock);
++ if (rc)
++ goto out;
++ spi = efx_mtd->spi;
++
++ rc = efx_spi_unlock(efx_mtd);
++ if (rc)
++ goto out_up;
++
++ while (pos < len) {
++ rc = efx_spi_write_enable(efx_mtd);
++ if (rc)
++ break;
++
++ block_len = min((unsigned int)len - pos,
++ efx_spi_write_limit(spi, start + pos));
++ command = efx_spi_munge_command(spi, SPI_WRITE, start + pos);
++ rc = spi->write(spi, efx_mtd->efx, command, start + pos,
++ buffer + pos, block_len);
++ if (rc)
++ break;
++ pos += block_len;
++
++ rc = efx_spi_fast_wait(efx_mtd);
++ if (rc)
++ break;
++
++ /* Avoid locking up the system */
++ cond_resched();
++ if (signal_pending(current)) {
++ rc = -EINTR;
++ break;
++ }
++ }
++
++out_up:
++ up(&efx_mtd->access_lock);
++ if (rc == 0)
++ rc = efx_mtd_verify(mtd, start, len, buffer, 0);
++out:
++ *retlen = pos;
++ return rc;
++}
++
++static void efx_mtd_sync(struct mtd_info *mtd)
++{
++ struct efx_mtd *efx_mtd = mtd->priv;
++ int rc;
++
++ down(&efx_mtd->access_lock);
++ rc = efx_spi_slow_wait(efx_mtd, 1);
++ if (rc)
++ EFX_ERR(efx_mtd->efx, "%s sync failed (%d)\n",
++ efx_mtd->name, rc);
++ up(&efx_mtd->access_lock);
++}
++
++/* Driverlink interface */
++
++static void efx_mtd_reset_suspend(struct efx_dl_device *efx_dev)
++{
++ struct efx_mtd *efx_mtd = efx_dev->priv;
++
++ if (!efx_mtd)
++ return;
++
++ /* Acquire lock to ensure that any in-progress operations have
++ * completed, and no new ones can start.
++ */
++ down(&efx_mtd->access_lock);
++}
++
++static void efx_mtd_reset_resume(struct efx_dl_device *efx_dev, int ok)
++{
++ struct efx_mtd *efx_mtd = efx_dev->priv;
++
++ if (!efx_mtd)
++ return;
++
++ /* If device reset failed already, or SPI device doesn't
++ * become ready, disable device.
++ */
++ if (!ok || efx_spi_slow_wait(efx_mtd, 1) != 0) {
++ efx_mtd->spi = &efx_spi_dummy_device;
++ EFX_ERR(efx_mtd->efx, "%s disabled after failed reset\n",
++ efx_mtd->name);
++ }
++
++ up(&efx_mtd->access_lock);
++}
++
++static void efx_mtd_remove(struct efx_dl_device *efx_dev)
++{
++ struct efx_mtd *efx_mtd = efx_dev->priv;
++
++ del_mtd_partitions(&efx_mtd->mtd);
++ kfree(efx_mtd);
++ efx_dev->priv = NULL;
++}
++
++static __devinit int efx_mtd_register(struct efx_mtd *efx_mtd,
++ struct efx_dl_device *efx_dev,
++ struct efx_nic *efx,
++ struct efx_spi_device *spi,
++ const char *type_name,
++ const char **part_type_name,
++ unsigned int num_parts)
++{
++ int i;
++
++ efx_dev->priv = efx_mtd;
++
++ efx_mtd->efx_dev = efx_dev;
++ efx_mtd->efx = efx;
++ efx_mtd->spi = spi;
++ sema_init(&efx_mtd->access_lock, 1);
++
++ efx_mtd->mtd.size = spi->size;
++ efx_mtd->mtd.erasesize = spi->erase_size;
++#if defined(EFX_USE_MTD_WRITESIZE)
++ efx_mtd->mtd.writesize = 1;
++#endif
++ if (snprintf(efx_mtd->name, sizeof(efx_mtd->name),
++ "%s %s", efx->name, type_name) >=
++ sizeof(efx_mtd->name))
++ return -ENAMETOOLONG;
++
++ efx_mtd->mtd.priv = efx_mtd;
++ efx_mtd->mtd.name = efx_mtd->name;
++ efx_mtd->mtd.erase = efx_mtd_erase;
++ efx_mtd->mtd.read = efx_mtd_read;
++ efx_mtd->mtd.write = efx_mtd_write;
++ efx_mtd->mtd.sync = efx_mtd_sync;
++
++ for (i = 0; i < num_parts; i++) {
++ efx_mtd->part[i].name = efx_mtd->part_name[i];
++ if (snprintf(efx_mtd->part_name[i],
++ sizeof(efx_mtd->part_name[i]),
++ "%s %s", efx->name, part_type_name[i]) >=
++ sizeof(efx_mtd->part_name[i]))
++ return -ENAMETOOLONG;
++
++ if (efx_allow_nvconfig_writes)
++ efx_mtd->part[i].mask_flags &= ~MTD_WRITEABLE;
++ }
++
++ return add_mtd_partitions(&efx_mtd->mtd, efx_mtd->part, num_parts);
++}
++
++static int __devinit
++efx_flash_probe(struct efx_dl_device *efx_dev,
++ const struct net_device *net_dev,
++ const struct efx_dl_device_info *dev_info,
++ const char *silicon_rev)
++{
++ struct efx_nic *efx = efx_dl_get_nic(efx_dev);
++ struct efx_mtd *efx_mtd;
++ const char *part_type_name[2];
++ unsigned int num_parts;
++ int rc;
++
++ if (!efx->spi_flash)
++ return -ENODEV;
++
++ efx_mtd = kzalloc(sizeof(*efx_mtd), GFP_KERNEL);
++ if (!efx_mtd)
++ return -ENOMEM;
++
++ efx_mtd->mtd.type = MTD_NORFLASH;
++ efx_mtd->mtd.flags = MTD_CAP_NORFLASH;
++
++ part_type_name[0] = "sfc_flash_config";
++ efx_mtd->part[0].offset = 0;
++ efx_mtd->part[0].size = min(efx->spi_flash->size,
++ EFX_FLASH_BOOTROM_OFFSET);
++ efx_mtd->part[0].mask_flags = MTD_WRITEABLE;
++
++ if (efx->spi_flash->size <= EFX_FLASH_BOOTROM_OFFSET) {
++ num_parts = 1;
++ } else {
++ part_type_name[1] = "sfc_flash_bootrom";
++ efx_mtd->part[1].offset = EFX_FLASH_BOOTROM_OFFSET;
++ efx_mtd->part[1].size = (efx->spi_flash->size
++ - EFX_FLASH_BOOTROM_OFFSET);
++ num_parts = 2;
++ }
++
++ rc = efx_mtd_register(efx_mtd, efx_dev, efx, efx->spi_flash,
++ "sfc_flash", part_type_name, num_parts);
++ if (rc)
++ kfree(efx_mtd);
++ return rc;
++}
++
++static struct efx_dl_driver efx_flash_driver = {
++ .name = "sfc_flash",
++ .probe = efx_flash_probe,
++ .remove = efx_mtd_remove,
++ .reset_suspend = efx_mtd_reset_suspend,
++ .reset_resume = efx_mtd_reset_resume,
++};
++
++static int __devinit
++efx_eeprom_probe(struct efx_dl_device *efx_dev,
++ const struct net_device *net_dev,
++ const struct efx_dl_device_info *dev_info,
++ const char *silicon_rev)
++{
++ struct efx_nic *efx = efx_dl_get_nic(efx_dev);
++ struct efx_mtd *efx_mtd;
++ const char *type_name;
++ const char *part_type_name[1];
++ int rc;
++
++ if (!efx->spi_eeprom)
++ return -ENODEV;
++
++ efx_mtd = kzalloc(sizeof(*efx_mtd), GFP_KERNEL);
++ if (!efx_mtd)
++ return -ENOMEM;
++
++ efx_mtd->mtd.type = MTD_RAM;
++ efx_mtd->mtd.flags = MTD_CAP_RAM;
++
++ efx_mtd->part[0].offset = 0;
++ efx_mtd->part[0].size = efx->spi_eeprom->size;
++ efx_mtd->part[0].mask_flags = MTD_WRITEABLE;
++
++ if (efx->spi_eeprom->size <= 0x200) {
++ type_name = "sfc_small_eeprom";
++ part_type_name[0] = "sfc_small_config";
++ } else {
++ type_name = "sfc_large_eeprom";
++ part_type_name[0] = "sfc_large_config";
++ }
++
++ rc = efx_mtd_register(efx_mtd, efx_dev, efx, efx->spi_eeprom,
++ type_name, part_type_name, 1);
++ if (rc)
++ kfree(efx_mtd);
++ return rc;
++}
++
++static struct efx_dl_driver efx_eeprom_driver = {
++ .name = "sfc_eeprom",
++ .probe = efx_eeprom_probe,
++ .remove = efx_mtd_remove,
++ .reset_suspend = efx_mtd_reset_suspend,
++ .reset_resume = efx_mtd_reset_resume,
++};
++
++/* Kernel module interface */
++
++static int __init efx_mtd_init_module(void)
++{
++ int rc;
++
++ rc = efx_dl_register_driver(&efx_flash_driver);
++ if (rc)
++ return rc;
++ rc = efx_dl_register_driver(&efx_eeprom_driver);
++ if (rc) {
++ efx_dl_unregister_driver(&efx_flash_driver);
++ return rc;
++ }
++
++ return 0;
++}
++
++static void __exit efx_mtd_exit_module(void)
++{
++ efx_dl_unregister_driver(&efx_eeprom_driver);
++ efx_dl_unregister_driver(&efx_flash_driver);
++}
++
++module_init(efx_mtd_init_module);
++module_exit(efx_mtd_exit_module);
++
++MODULE_AUTHOR("Michael Brown <mbrown@fensystems.co.uk> and "
++ "Solarflare Communications");
++MODULE_DESCRIPTION("SFC MTD driver");
++MODULE_LICENSE("GPL");
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/net_driver.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/net_driver.h
+--- linux-2.6.18.8/drivers/net/sfc/net_driver.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/net_driver.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1096 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/* Common definitions for all Efx net driver code */
++
++#ifndef EFX_NET_DRIVER_H
++#define EFX_NET_DRIVER_H
++
++#include <linux/version.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ethtool.h>
++#include <linux/if_vlan.h>
++#include <linux/timer.h>
++#include <linux/mii.h>
++#include <linux/list.h>
++#include <linux/pci.h>
++#include <linux/device.h>
++
++/* Must come before other headers */
++#include "kernel_compat.h"
++
++#include "enum.h"
++#include "bitfield.h"
++#include "driverlink_api.h"
++#include "driverlink.h"
++#include "i2c-direct.h"
++
++ #ifndef EFX_USE_DEBUGFS
++ /* Sick, but we have no other use for dentry */
++ #define dentry proc_dir_entry
++ #endif
++
++#define EFX_MAX_LRO_DESCRIPTORS 8
++#define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS
++
++/**************************************************************************
++ *
++ * Build definitions
++ *
++ **************************************************************************/
++#ifndef EFX_DRIVER_NAME
++#define EFX_DRIVER_NAME "sfc"
++#endif
++#define EFX_DRIVER_VERSION "2.2.0101"
++
++#ifdef EFX_ENABLE_DEBUG
++#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
++#define EFX_WARN_ON_PARANOID(x) WARN_ON(x)
++#else
++#define EFX_BUG_ON_PARANOID(x) do {} while (0)
++#define EFX_WARN_ON_PARANOID(x) do {} while (0)
++#endif
++
++/* Include net device name in log messages if it has been registered.
++ * Use efx->name not efx->net_dev->name so that races with (un)registration
++ * are harmless.
++ */
++#define NET_DEV_NAME(efx) ((efx)->net_dev_registered ? (efx)->name : "")
++
++/* Un-rate-limited logging */
++#define EFX_ERR(efx, fmt, args...) \
++dev_err(&((efx)->pci_dev->dev), "ERR: %s " fmt, NET_DEV_NAME(efx), ##args)
++
++#define EFX_INFO(efx, fmt, args...) \
++dev_info(&((efx)->pci_dev->dev), "INFO: %s " fmt, NET_DEV_NAME(efx), ##args)
++
++#ifdef EFX_ENABLE_DEBUG
++#define EFX_LOG(efx, fmt, args...) \
++dev_info(&((efx)->pci_dev->dev), "DBG: %s " fmt, NET_DEV_NAME(efx), ##args)
++#else
++#define EFX_LOG(efx, fmt, args...) \
++dev_dbg(&((efx)->pci_dev->dev), "DBG: %s " fmt, NET_DEV_NAME(efx), ##args)
++#endif
++
++#define EFX_TRACE(efx, fmt, args...) do {} while (0)
++
++#define EFX_REGDUMP(efx, fmt, args...) do {} while (0)
++
++/* Rate-limited logging */
++#define EFX_ERR_RL(efx, fmt, args...) \
++do {if (net_ratelimit()) EFX_ERR(efx, fmt, ##args); } while (0)
++
++#define EFX_INFO_RL(efx, fmt, args...) \
++do {if (net_ratelimit()) EFX_INFO(efx, fmt, ##args); } while (0)
++
++#define EFX_LOG_RL(efx, fmt, args...) \
++do {if (net_ratelimit()) EFX_LOG(efx, fmt, ##args); } while (0)
++
++/* Kernel headers may redefine inline anyway */
++#ifndef inline
++#define inline inline __attribute__ ((always_inline))
++#endif
++
++/**************************************************************************
++ *
++ * Efx data structures
++ *
++ **************************************************************************/
++
++#define EFX_MAX_CHANNELS 32
++#define EFX_MAX_TX_QUEUES 1
++#define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS
++
++/**
++ * struct efx_special_buffer - An Efx special buffer
++ * @addr: CPU base address of the buffer
++ * @dma_addr: DMA base address of the buffer
++ * @len: Buffer length, in bytes
++ * @index: Buffer index within controller;s buffer table
++ * @entries: Number of buffer table entries
++ *
++ * Special buffers are used for the event queues and the TX and RX
++ * descriptor queues for each channel. They are *not* used for the
++ * actual transmit and receive buffers.
++ *
++ * Note that for Falcon, TX and RX descriptor queues live in host memory.
++ * Allocation and freeing procedures must take this into account.
++ */
++struct efx_special_buffer {
++ void *addr;
++ dma_addr_t dma_addr;
++ unsigned int len;
++ int index;
++ int entries;
++};
++
++/**
++ * struct efx_tx_buffer - An Efx TX buffer
++ * @skb: The associated socket buffer.
++ * Set only on the final fragment of a packet; %NULL for all other
++ * fragments. When this fragment completes, then we can free this
++ * skb.
++ * @dma_addr: DMA address of the fragment.
++ * @len: Length of this fragment.
++ * This field is zero when the queue slot is empty.
++ * @continuation: True if this fragment is not the end of a packet.
++ * @unmap_single: True if pci_unmap_single should be used.
++ * @unmap_addr: DMA address to unmap
++ * @unmap_len: Length of this fragment to unmap
++ */
++struct efx_tx_buffer {
++ const struct sk_buff *skb;
++ dma_addr_t dma_addr;
++ unsigned short len;
++ unsigned char continuation;
++ unsigned char unmap_single;
++ dma_addr_t unmap_addr;
++ unsigned short unmap_len;
++};
++
++/**
++ * struct efx_tx_queue - An Efx TX queue
++ *
++ * This is a ring buffer of TX fragments.
++ * Since the TX completion path always executes on the same
++ * CPU and the xmit path can operate on different CPUs,
++ * performance is increased by ensuring that the completion
++ * path and the xmit path operate on different cache lines.
++ * This is particularly important if the xmit path is always
++ * executing on one CPU which is different from the completion
++ * path. There is also a cache line for members which are
++ * read but not written on the fast path.
++ *
++ * @efx: The associated Efx NIC
++ * @queue: DMA queue number
++ * @used: Queue is used by net driver
++ * @channel: The associated channel
++ * @buffer: The software buffer ring
++ * @txd: The hardware descriptor ring
++ * @debug_dir: debugfs directory
++ * @read_count: Current read pointer.
++ * This is the number of buffers that have been removed from both rings.
++ * @stopped: Stopped flag.
++ * Set if this TX queue is currently stopping its port.
++ * @insert_count: Current insert pointer
++ * This is the number of buffers that have been added to the
++ * software ring.
++ * @write_count: Current write pointer
++ * This is the number of buffers that have been added to the
++ * hardware ring.
++ * @old_read_count: The value of read_count when last checked.
++ * This is here for performance reasons. The xmit path will
++ * only get the up-to-date value of read_count if this
++ * variable indicates that the queue is full. This is to
++ * avoid cache-line ping-pong between the xmit path and the
++ * completion path.
++ */
++struct efx_tx_queue {
++ /* Members which don't change on the fast path */
++ struct efx_nic *efx ____cacheline_aligned_in_smp;
++ int queue;
++ int used;
++ struct efx_channel *channel;
++ struct efx_nic *nic;
++ struct efx_tx_buffer *buffer;
++ struct efx_special_buffer txd;
++#ifdef CONFIG_SFC_DEBUGFS
++ struct dentry *debug_dir;
++#endif
++
++ /* Members used mainly on the completion path */
++ unsigned int read_count ____cacheline_aligned_in_smp;
++ int stopped;
++
++ /* Members used only on the xmit path */
++ unsigned int insert_count ____cacheline_aligned_in_smp;
++ unsigned int write_count;
++ unsigned int old_read_count;
++};
++
++/**
++ * struct efx_rx_buffer - An Efx RX data buffer
++ * @dma_addr: DMA base address of the buffer
++ * @skb: The associated socket buffer, if any.
++ * If both this and page are %NULL, the buffer slot is currently free.
++ * @page: The associated page buffer, if any.
++ * If both this and skb are %NULL, the buffer slot is currently free.
++ * @data: Pointer to ethernet header
++ * @len: Buffer length, in bytes.
++ * @unmap_addr: DMA address to unmap
++ */
++struct efx_rx_buffer {
++ dma_addr_t dma_addr;
++ struct sk_buff *skb;
++ struct page *page;
++ char *data;
++ unsigned int len;
++ dma_addr_t unmap_addr;
++};
++
++/**
++ * struct efx_rx_queue - An Efx RX queue
++ * @efx: The associated Efx NIC
++ * @queue: DMA queue number
++ * @used: Queue is used by net driver
++ * @channel: The associated channel
++ * @buffer: The software buffer ring
++ * @rxd: The hardware descriptor ring
++ * @added_count: Number of buffers added to the receive queue.
++ * @notified_count: Number of buffers given to NIC (<= @added_count).
++ * @removed_count: Number of buffers removed from the receive queue.
++ * @add_lock: Receive queue descriptor add spin lock.
++ * This lock must be held in order to add buffers to the RX
++ * descriptor ring (rxd and buffer) and to update added_count (but
++ * not removed_count).
++ * @max_fill: RX descriptor maximum fill level (<= ring size)
++ * @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill
++ * (<= @max_fill)
++ * @fast_fill_limit: The level to which a fast fill will fill
++ * (@fast_fill_trigger <= @fast_fill_limit <= @max_fill)
++ * @min_fill: RX descriptor minimum non-zero fill level.
++ * This records the minimum fill level observed when a ring
++ * refill was triggered.
++ * @min_overfill: RX descriptor minimum overflow fill level.
++ * This records the minimum fill level at which RX queue
++ * overflow was observed. It should never be set.
++ * @alloc_page_count: RX allocation strategy counter.
++ * @alloc_skb_count: RX allocation strategy counter.
++ * @work: Descriptor push work thread
++ * @buf_page: Page for next RX buffer.
++ * We can use a single page for multiple RX buffers. This tracks
++ * the remaining space in the allocation.
++ * @buf_dma_addr: Page's DMA address.
++ * @buf_data: Page's host address.
++ * @debug_dir: debugfs directory
++ */
++struct efx_rx_queue {
++ struct efx_nic *efx;
++ int queue;
++ int used;
++ struct efx_channel *channel;
++ struct efx_rx_buffer *buffer;
++ struct efx_special_buffer rxd;
++
++ int added_count;
++ int notified_count;
++ int removed_count;
++ spinlock_t add_lock;
++ unsigned int max_fill;
++ unsigned int fast_fill_trigger;
++ unsigned int fast_fill_limit;
++ unsigned int min_fill;
++ unsigned int min_overfill;
++ unsigned int alloc_page_count;
++ unsigned int alloc_skb_count;
++ struct delayed_work work;
++ unsigned int slow_fill_count;
++
++ struct page *buf_page;
++ dma_addr_t buf_dma_addr;
++ char *buf_data;
++
++#ifdef CONFIG_SFC_DEBUGFS
++ struct dentry *debug_dir;
++#endif
++};
++
++/**
++ * struct efx_buffer - An Efx general-purpose buffer
++ * @addr: host base address of the buffer
++ * @dma_addr: DMA base address of the buffer
++ * @len: Buffer length, in bytes
++ *
++ * Falcon uses these buffers for its interrupt status registers and
++ * MAC stats dumps.
++ */
++struct efx_buffer {
++ void *addr;
++ dma_addr_t dma_addr;
++ unsigned int len;
++};
++
++
++/* Flags for channel->used_flags */
++#define EFX_USED_BY_RX 1
++#define EFX_USED_BY_TX 2
++#define EFX_USED_BY_RX_TX (EFX_USED_BY_RX | EFX_USED_BY_TX)
++
++enum efx_rx_alloc_method {
++ RX_ALLOC_METHOD_AUTO = 0,
++ RX_ALLOC_METHOD_SKB = 1,
++ RX_ALLOC_METHOD_PAGE = 2,
++};
++
++/**
++ * struct efx_channel - An Efx channel
++ *
++ * A channel comprises an event queue, at least one TX queue, at least
++ * one RX queue, and an associated tasklet for processing the event
++ * queue.
++ *
++ * @efx: Associated Efx NIC
++ * @evqnum: Event queue number
++ * @channel: Channel instance number
++ * @used_flags: Channel is used by net driver
++ * @enabled: Channel enabled indicator
++ * @irq: IRQ number (MSI and MSI-X only)
++ * @has_interrupt: Channel has an interrupt
++ * @irq_moderation: IRQ moderation value (in us)
++ * @napi_dev: Net device used with NAPI
++ * @napi_str: NAPI control structure
++ * @reset_work: Scheduled reset work thread
++ * @work_pending: Is work pending via NAPI?
++ * @eventq: Event queue buffer
++ * @eventq_read_ptr: Event queue read pointer
++ * @last_eventq_read_ptr: Last event queue read pointer value.
++ * @eventq_magic: Event queue magic value for driver-generated test events
++ * @debug_dir: debugfs directory
++ * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
++ * and diagnostic counters
++ * @rx_alloc_push_pages: RX allocation method currently in use for pushing
++ * descriptors
++ * @rx_alloc_pop_pages: RX allocation method currently in use for popping
++ * descriptors
++ * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
++ * @n_rx_ip_frag_err: Count of RX IP fragment errors
++ * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
++ * @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
++ * @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors
++ * @n_rx_overlength: Count of RX_OVERLENGTH errors
++ * @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
++ */
++struct efx_channel {
++ struct efx_nic *efx;
++ int evqnum;
++ int channel;
++ int used_flags;
++ int enabled;
++ int irq;
++ unsigned int has_interrupt;
++ unsigned int irq_moderation;
++ struct net_device *napi_dev;
++#if !defined(EFX_HAVE_OLD_NAPI)
++ struct napi_struct napi_str;
++#endif
++ struct work_struct reset_work;
++ int work_pending;
++ struct efx_special_buffer eventq;
++ unsigned int eventq_read_ptr;
++ unsigned int last_eventq_read_ptr;
++ unsigned int eventq_magic;
++
++#ifdef CONFIG_SFC_DEBUGFS
++ struct dentry *debug_dir;
++#endif
++
++ int rx_alloc_level;
++ int rx_alloc_push_pages;
++ int rx_alloc_pop_pages;
++
++ unsigned n_rx_tobe_disc;
++ unsigned n_rx_ip_frag_err;
++ unsigned n_rx_ip_hdr_chksum_err;
++ unsigned n_rx_tcp_udp_chksum_err;
++ unsigned n_rx_frm_trunc;
++ unsigned n_rx_overlength;
++ unsigned n_skbuff_leaks;
++
++ /* Used to pipeline received packets in order to optimise memory
++ * access with prefetches.
++ */
++ struct efx_rx_buffer *rx_pkt;
++ int rx_pkt_csummed;
++
++};
++
++/**
++ * struct efx_blinker - S/W LED blinking context
++ * @led_num: LED ID (board-specific meaning)
++ * @state: Current state - on or off
++ * @resubmit: Timer resubmission flag
++ * @timer: Control timer for blinking
++ */
++struct efx_blinker {
++ int led_num;
++ int state;
++ int resubmit;
++ struct timer_list timer;
++};
++
++
++/**
++ * struct efx_board - board information
++ * @type: Board model type
++ * @major: Major rev. ('A', 'B' ...)
++ * @minor: Minor rev. (0, 1, ...)
++ * @init: Initialisation function
++ * @init_leds: Sets up board LEDs
++ * @set_fault_led: Turns the fault LED on or off
++ * @blink: Starts/stops blinking
++ * @monitor: Board-specific health check function
++ * @fini: Cleanup function
++ * @interpret_sensor: Function to interpret LM87 sensor meanings.
++ * Returns %FALSE if no board-specific meaning.
++ * @mwatts: Power requirements (mW)
++ * @blinker: used to blink LEDs in software
++ * @lm87_addr: I2C address of LM87 monitoring chip (0 if absent)
++ */
++struct efx_board {
++ int type;
++ int major;
++ int minor;
++ int (*init) (struct efx_nic *nic);
++ /* As the LEDs are typically attached to the PHY, LEDs
++ * have a separate init callback that happens later than
++ * board init. */
++ int (*init_leds)(struct efx_nic *efx);
++ int (*monitor) (struct efx_nic *nic);
++ void (*set_fault_led) (struct efx_nic *efx, int state);
++ void (*blink) (struct efx_nic *efx, int start);
++ void (*fini) (struct efx_nic *nic);
++ int (*interpret_sensor) (struct efx_nic *nic, int num, unsigned val);
++ unsigned mwatts;
++ struct efx_blinker blinker;
++ unsigned int lm87_addr;
++};
++
++#define STRING_TABLE_LOOKUP(val, member) \
++ ((val) < member ## _max) ? member ## _names[val] : "(invalid)"
++
++extern const char *efx_loopback_mode_names[];
++extern const unsigned int efx_loopback_mode_max;
++#define LOOPBACK_MODE(efx) \
++ STRING_TABLE_LOOKUP((efx)->loopback_mode, efx_loopback_mode)
++
++extern const char *efx_interrupt_mode_names[];
++extern const unsigned int efx_interrupt_mode_max;
++#define INT_MODE(efx) \
++ STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode)
++
++extern const char *efx_reset_type_names[];
++extern const unsigned int efx_reset_type_max;
++#define RESET_TYPE(type) \
++ STRING_TABLE_LOOKUP(type, efx_reset_type)
++
++extern const char *efx_phy_type_names[];
++extern const unsigned int efx_phy_type_max;
++#define PHY_TYPE(efx) \
++ STRING_TABLE_LOOKUP((efx)->phy_type, efx_phy_type)
++
++extern const char *efx_nic_state_names[];
++extern const unsigned int efx_nic_state_max;
++#define STATE_NAME(efx) \
++ STRING_TABLE_LOOKUP((efx)->state, efx_nic_state)
++
++enum efx_int_mode {
++ /* Be careful if altering to correct macro below */
++ EFX_INT_MODE_MSIX = 0,
++ EFX_INT_MODE_MSI = 1,
++ EFX_INT_MODE_LEGACY = 2,
++ EFX_INT_MODE_MAX /* Insert any new items before this */
++};
++#define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI)
++
++enum phy_type {
++ PHY_TYPE_NONE = 0,
++ PHY_TYPE_CX4_RTMR = 1,
++ PHY_TYPE_1G_ALASKA = 2,
++ PHY_TYPE_10XPRESS = 3,
++ PHY_TYPE_XFP = 4,
++ PHY_TYPE_PM8358 = 6,
++ PHY_TYPE_MAX /* Insert any new items before this */
++};
++
++#define PHY_ADDR_INVALID 0xff
++
++#define EFX_IS10G(efx) ((efx)->is_10g)
++#define EFX_ISCLAUSE45(efx) ((efx)->phy_type != PHY_TYPE_1G_ALASKA)
++
++enum nic_state {
++ STATE_INIT = 0, /* suspend_lock always held */
++ STATE_RUNNING = 1,
++ STATE_FINI = 2,
++ STATE_RESETTING = 3, /* suspend_lock always held */
++ STATE_DISABLED = 4,
++ STATE_MAX,
++};
++
++/*
++ * Alignment of page-allocated RX buffers
++ *
++ * Controls the number of bytes inserted at the start of an RX buffer.
++ * This is the equivalent of NET_IP_ALIGN [which controls the alignment
++ * of the skb->head for hardware DMA].
++ */
++#ifdef __ia64__
++#define EFX_PAGE_IP_ALIGN 2
++#else
++#define EFX_PAGE_IP_ALIGN 0
++#endif
++
++/*
++ * Alignment of the skb->head which wraps a page-allocated RX buffer
++ *
++ * The skb allocated to wrap an rx_buffer can have this alignment. Since
++ * the data is memcpy'd from the rx_buf, it does not need to be equal to
++ * EFX_PAGE_IP_ALIGN.
++ */
++#define EFX_PAGE_SKB_ALIGN 2
++
++/* Forward declaration */
++struct efx_nic;
++
++/* Pseudo bit-mask flow control field */
++enum efx_fc_type {
++ EFX_FC_RX = 1,
++ EFX_FC_TX = 2,
++ EFX_FC_AUTO = 4,
++};
++
++/**
++ * struct efx_mac_operations - Efx MAC operations table
++ * @mac_writel: Write dword to MAC register
++ * @mac_readl: Read dword from a MAC register
++ * @init: Initialise MAC and PHY
++ * @reconfigure: Reconfigure MAC and PHY (e.g. for new link parameters)
++ * @update_stats: Update statistics
++ * @fini: Shut down MAC and PHY
++ * @check_hw: Check hardware
++ * @fake_phy_event: Simulate a PHY event on a port
++ * @get_settings: Get ethtool settings
++ * @set_settings: Set ethtool settings
++ * @set_pause: Set pause parameters
++ */
++struct efx_mac_operations {
++ void (*mac_writel) (struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg);
++ void (*mac_readl) (struct efx_nic *efx,
++ efx_dword_t *value, unsigned int mac_reg);
++ int (*init) (struct efx_nic *efx);
++ void (*reconfigure) (struct efx_nic *efx);
++ void (*update_stats) (struct efx_nic *efx);
++ void (*fini) (struct efx_nic *efx);
++ int (*check_hw) (struct efx_nic *efx);
++ void (*fake_phy_event) (struct efx_nic *efx);
++
++ int (*get_settings) (struct efx_nic *efx,
++ struct ethtool_cmd *ecmd);
++ int (*set_settings) (struct efx_nic *efx,
++ struct ethtool_cmd *ecmd);
++ int (*set_pause) (struct efx_nic *efx,
++ enum efx_fc_type pause_params);
++};
++
++/**
++ * struct efx_phy_operations - Efx PHY operations table
++ * @init: Initialise PHY
++ * @fini: Shut down PHY
++ * @reconfigure: Reconfigure PHY (e.g. for new link parameters)
++ * @clear_interrupt: Clear down interrupt
++ * @blink: Blink LEDs
++ * @check_hw: Check hardware
++ * @reset_xaui: Reset XAUI side of PHY for (software sequenced reset)
++ * @mmds: MMD presence mask
++ * @loopbacks: Supported loopback modes mask
++ * @startup_loopback: Loopback mode for start-of-day self-test
++ */
++struct efx_phy_operations {
++ int (*init) (struct efx_nic *efx);
++ void (*fini) (struct efx_nic *efx);
++ void (*reconfigure) (struct efx_nic *efx);
++ void (*clear_interrupt) (struct efx_nic *efx);
++ int (*check_hw) (struct efx_nic *efx);
++ void (*reset_xaui) (struct efx_nic *efx);
++ int mmds;
++ unsigned loopbacks;
++ unsigned startup_loopback;
++};
++
++/*
++ * Efx extended statistics
++ *
++ * Not all statistics are provided by all supported MACs. The purpose
++ * is this structure is to contain the raw statistics provided by each
++ * MAC.
++ */
++struct efx_mac_stats {
++ u64 tx_bytes;
++ u64 tx_good_bytes;
++ u64 tx_bad_bytes;
++ unsigned long tx_packets;
++ unsigned long tx_bad;
++ unsigned long tx_pause;
++ unsigned long tx_control;
++ unsigned long tx_unicast;
++ unsigned long tx_multicast;
++ unsigned long tx_broadcast;
++ unsigned long tx_lt64;
++ unsigned long tx_64;
++ unsigned long tx_65_to_127;
++ unsigned long tx_128_to_255;
++ unsigned long tx_256_to_511;
++ unsigned long tx_512_to_1023;
++ unsigned long tx_1024_to_15xx;
++ unsigned long tx_15xx_to_jumbo;
++ unsigned long tx_gtjumbo;
++ unsigned long tx_collision;
++ unsigned long tx_single_collision;
++ unsigned long tx_multiple_collision;
++ unsigned long tx_excessive_collision;
++ unsigned long tx_deferred;
++ unsigned long tx_late_collision;
++ unsigned long tx_excessive_deferred;
++ unsigned long tx_non_tcpudp;
++ unsigned long tx_mac_src_error;
++ unsigned long tx_ip_src_error;
++ u64 rx_bytes;
++ u64 rx_good_bytes;
++ u64 rx_bad_bytes;
++ unsigned long rx_packets;
++ unsigned long rx_good;
++ unsigned long rx_bad;
++ unsigned long rx_pause;
++ unsigned long rx_control;
++ unsigned long rx_unicast;
++ unsigned long rx_multicast;
++ unsigned long rx_broadcast;
++ unsigned long rx_lt64;
++ unsigned long rx_64;
++ unsigned long rx_65_to_127;
++ unsigned long rx_128_to_255;
++ unsigned long rx_256_to_511;
++ unsigned long rx_512_to_1023;
++ unsigned long rx_1024_to_15xx;
++ unsigned long rx_15xx_to_jumbo;
++ unsigned long rx_gtjumbo;
++ unsigned long rx_bad_lt64;
++ unsigned long rx_bad_64_to_15xx;
++ unsigned long rx_bad_15xx_to_jumbo;
++ unsigned long rx_bad_gtjumbo;
++ unsigned long rx_overflow;
++ unsigned long rx_missed;
++ unsigned long rx_false_carrier;
++ unsigned long rx_symbol_error;
++ unsigned long rx_align_error;
++ unsigned long rx_length_error;
++ unsigned long rx_internal_error;
++ unsigned long rx_good_lt64;
++};
++
++/* Number of bits used in a multicast filter hash address */
++#define EFX_MCAST_HASH_BITS 8
++
++/* Number of (single-bit) entries in a multicast filter hash */
++#define EFX_MCAST_HASH_ENTRIES (1 << EFX_MCAST_HASH_BITS)
++
++/* An Efx multicast filter hash */
++union efx_multicast_hash {
++ u8 byte[EFX_MCAST_HASH_ENTRIES / sizeof(u8)];
++ efx_oword_t oword[EFX_MCAST_HASH_ENTRIES / sizeof(efx_oword_t)];
++};
++
++/* Efx Error condition statistics */
++struct efx_nic_errors {
++ atomic_t missing_event;
++ atomic_t rx_reset;
++ atomic_t rx_desc_fetch;
++ atomic_t tx_desc_fetch;
++ atomic_t spurious_tx;
++
++#ifdef CONFIG_SFC_DEBUGFS
++ struct dentry *debug_dir;
++#endif
++};
++
++/**
++ * struct efx_nic - an Efx NIC
++ * @name: Device name (net device name or bus id before net device registered)
++ * @pci_dev: The PCI device
++ * @pci_dev2: The secondary PCI device if present
++ * @type: Controller type attributes
++ * @dma_mask: DMA mask
++ * @legacy_irq: IRQ number
++ * @workqueue: Workqueue for resets, port reconfigures and the HW monitor
++ * @refill_workqueue: RX refill workqueue
++ * @reset_work: Scheduled reset workitem
++ * @monitor_work: Hardware monitor workitem
++ * @membase_phys: Memory BAR value as physical address
++ * @membase: Memory BAR value
++ * @biu_lock: BIU (bus interface unit) lock
++ * @interrupt_mode: Interrupt mode
++ * @is_asic: Is ASIC (else FPGA)
++ * @is_10g: Is set to 10G (else 1G)
++ * @external_sram_cfg: Size and number of banks of external SRAM
++ * @i2c: I2C interface
++ * @board_info: Board-level information
++ * @state: Device state flag. Can only be manipulated when both
++ * suspend_lock and rtnl_lock are held. Can be read when
++ * either is held.
++ * @reset_pending: Pending reset method (normally RESET_TYPE_NONE)
++ * @suspend_lock: Device suspend lock. This must not be acquired with
++ * rtnl_lock held.
++ * @tx_queue: TX DMA queues
++ * @rx_queue: RX DMA queues
++ * @channel: Channels
++ * @rss_queues: Number of RSS queues
++ * @rx_buffer_len: RX buffer length
++ * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
++ * @errors: Error condition stats
++ * @irq_status: Interrupt status buffer
++ * @last_irq_cpu: Last CPU to handle interrupt.
++ * This register is written with the SMP processor ID whenever an
++ * interrupt is handled. It is used by falcon_test_interrupt()
++ * to verify that an interrupt has occurred.
++ * @spi_flash: SPI flash device
++ * This field will be %NULL if no flash device is present.
++ * @spi_eeprom: SPI EEPROM device
++ * This field will be %NULL if no EEPROM device is present.
++ * @spi_lock: SPI bus lock
++ * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
++ * @nic_data: Hardware dependant state
++ * @mac_lock: MAC access lock. Protects efx->port_enabled/net_dev_registered
++ * and efx_reconfigure_port()
++ * @port_enabled: Port enabled indicator.
++ * Serialises efx_stop_all and efx_start_all with kernel interfaces.
++ * Safe to read under the rtnl_lock, mac_lock, or netif_tx_lock, but
++ * all three must be held to modify it.
++ * @net_dev_registered: Port is registered with operating system.
++ * @port_initialized: Port initialized?
++ * @net_dev: Operating system network device. Consider holding the rtnl lock
++ * @rx_checksum_enabled: RX checksumming enabled
++ * @netif_stop_count: Port stop count
++ * @netif_stop_lock: Port stop lock
++ * @mac_stats: MAC statistics
++ * @stats: Net device statistics.
++ * Hardware-specific code fills in @mac_stats, which provides a
++ * detailed breakdown. Generic code aggregates these statistics
++ * into a standard &struct net_device_stats.
++ * @stats_buffer: DMA buffer for statistics
++ * @stats_lock: Statistics update lock
++ * @mac_op: MAC interface
++ * @mac_address: Permanent MAC address
++ * @phy_type: PHY type
++ * @phy_lock: PHY access lock
++ * @phy_op: PHY interface
++ * @phy_data: PHY private data (including PHY-specific stats)
++ * @mii: PHY interface
++ * @phy_powered: PHY power state
++ * @tx_disabled: PHY transmitter turned off
++ * @link_up: Link status
++ * @link_options: Link options (MII/GMII format)
++ * @n_link_state_changes: Number of times the link has changed state
++ * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
++ * @multicast_hash: Multicast hash table
++ * @flow_control: Flow control flags - separate RX/TX so can't use link_options
++ * @reconfigure_work: work item for dealing with PHY events
++ * @loopback_mode: Loopback status
++ * @loopback_modes: Supported loopback mode bitmask
++ * @loopback_selftest: Offline self-test private state
++ * @silicon_rev: Silicon revision description for driverlink
++ * @dl_info: Linked list of hardware parameters exposed through driverlink
++ * @dl_node: Driverlink port list
++ * @dl_device_list: Driverlink device list
++ * @dl_cb: Driverlink callbacks table
++ * @dl_cb_dev: Driverlink callback owner devices
++ * @debug_dir: NIC debugfs directory
++ * @debug_symlink: NIC debugfs sym-link (nic_eth\%d)
++ * @debug_port_dir: Port debugfs directory
++ * @debug_port_symlink: Port debugfs sym-link (if_eth\%d)
++ *
++ * The @priv field of the corresponding &struct net_device points to
++ * this.
++ */
++struct efx_nic {
++ char name[IFNAMSIZ];
++ struct pci_dev *pci_dev;
++ struct pci_dev *pci_dev2;
++#if !defined(EFX_USE_PCI_DEV_REVISION)
++ u8 revision;
++#endif
++ const struct efx_nic_type *type;
++ dma_addr_t dma_mask;
++ int legacy_irq;
++ struct workqueue_struct *workqueue;
++#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
++ /* Since we can't use cancel_delayed_work_sync efx_reset() has to
++ * flush efx->workqueue to serialise against efx_reconfigure_port
++ * and efx_monitor. So it can't also run on workqueue */
++ struct workqueue_struct *reset_workqueue;
++#endif
++ struct workqueue_struct *refill_workqueue;
++ struct work_struct reset_work;
++ struct delayed_work monitor_work;
++ unsigned long membase_phys;
++ void __iomem *membase;
++ spinlock_t biu_lock;
++ enum efx_int_mode interrupt_mode;
++ unsigned int is_asic:1;
++ unsigned int is_10g:1;
++ int external_sram_cfg;
++
++ struct efx_i2c_interface i2c;
++ struct efx_board board_info;
++
++ enum nic_state state;
++ enum reset_type reset_pending;
++
++ struct semaphore suspend_lock;
++
++ struct efx_tx_queue tx_queue[EFX_MAX_TX_QUEUES];
++ struct efx_rx_queue rx_queue[EFX_MAX_RX_QUEUES];
++ struct efx_channel channel[EFX_MAX_CHANNELS];
++
++ int rss_queues;
++ unsigned int rx_buffer_len;
++ unsigned int rx_buffer_order;
++
++ struct efx_nic_errors errors;
++
++ struct efx_buffer irq_status;
++ volatile signed int last_irq_cpu;
++
++ struct efx_spi_device *spi_flash;
++ struct efx_spi_device *spi_eeprom;
++ struct mutex spi_lock;
++
++ unsigned n_rx_nodesc_drop_cnt;
++
++ void *nic_data;
++
++ struct mutex mac_lock;
++ int port_enabled;
++ int net_dev_registered;
++
++ int port_initialized;
++ struct net_device *net_dev;
++ int rx_checksum_enabled;
++
++ atomic_t netif_stop_count;
++ spinlock_t netif_stop_lock;
++
++ struct efx_mac_stats mac_stats;
++ struct net_device_stats stats;
++ struct efx_buffer stats_buffer;
++ spinlock_t stats_lock;
++
++ struct efx_mac_operations *mac_op;
++ unsigned char mac_address[ETH_ALEN];
++
++ enum phy_type phy_type;
++ spinlock_t phy_lock;
++ struct efx_phy_operations *phy_op;
++ void *phy_data;
++ struct mii_if_info mii;
++ unsigned phy_powered;
++ unsigned tx_disabled;
++
++ int link_up;
++ unsigned int link_options;
++ unsigned int n_link_state_changes;
++
++ int promiscuous;
++ union efx_multicast_hash multicast_hash;
++ enum efx_fc_type flow_control;
++ struct work_struct reconfigure_work;
++
++ enum efx_loopback_mode loopback_mode;
++ unsigned int loopback_modes;
++ unsigned int startup_loopbacks;
++
++ void *loopback_selftest;
++
++ const char *silicon_rev;
++ struct efx_dl_device_info *dl_info;
++ struct list_head dl_node;
++ struct list_head dl_device_list;
++ struct efx_dl_callbacks dl_cb;
++ struct efx_dl_cb_devices dl_cb_dev;
++
++#ifdef CONFIG_SFC_DEBUGFS
++ struct dentry *debug_dir;
++ struct dentry *debug_symlink;
++ struct dentry *debug_port_dir;
++ struct dentry *debug_port_symlink;
++#endif
++};
++
++/**
++ * struct efx_nic_type - Efx device type definition
++ * @is_dual_func: Is dual-function (else single-function)
++ * @mem_bar: Memory BAR number
++ * @mem_map_size: Memory BAR mapped size
++ * @txd_ptr_tbl_base: TX descriptor ring base address
++ * @rxd_ptr_tbl_base: RX descriptor ring base address
++ * @buf_tbl_base: Buffer table base address
++ * @evq_ptr_tbl_base: Event queue pointer table base address
++ * @evq_rptr_tbl_base: Event queue read-pointer table base address
++ * @txd_ring_mask: TX descriptor ring size - 1 (must be a power of two - 1)
++ * @rxd_ring_mask: RX descriptor ring size - 1 (must be a power of two - 1)
++ * @evq_size: Event queue size (must be a power of two)
++ * @max_dma_mask: Maximum possible DMA mask
++ * @tx_dma_mask: TX DMA mask
++ * @bug5391_mask: Address mask for bug 5391 workaround
++ * @rx_xoff_thresh: RX FIFO XOFF watermark (bytes)
++ * @rx_xon_thresh: RX FIFO XON watermark (bytes)
++ * @rx_buffer_padding: Padding added to each RX buffer
++ * @max_interrupt_mode: Highest capability interrupt mode supported
++ * from &enum efx_init_mode.
++ * @phys_addr_channels: Number of channels with physically addressed
++ * descriptors
++ */
++struct efx_nic_type {
++ unsigned int is_dual_func;
++ unsigned int mem_bar;
++ unsigned int mem_map_size;
++ unsigned int txd_ptr_tbl_base;
++ unsigned int rxd_ptr_tbl_base;
++ unsigned int buf_tbl_base;
++ unsigned int evq_ptr_tbl_base;
++ unsigned int evq_rptr_tbl_base;
++
++ unsigned int txd_ring_mask;
++ unsigned int rxd_ring_mask;
++ unsigned int evq_size;
++ dma_addr_t max_dma_mask;
++ unsigned int tx_dma_mask;
++ unsigned bug5391_mask;
++
++ int rx_xoff_thresh;
++ int rx_xon_thresh;
++ unsigned int rx_buffer_padding;
++ unsigned int max_interrupt_mode;
++ unsigned int phys_addr_channels;
++};
++
++/**************************************************************************
++ *
++ * Prototypes and inline functions
++ *
++ *************************************************************************/
++
++/* Iterate over all used channels */
++#define efx_for_each_channel(_channel, _efx) \
++ for (_channel = &_efx->channel[0]; \
++ _channel < &_efx->channel[EFX_MAX_CHANNELS]; \
++ _channel++) \
++ if (!_channel->used_flags) \
++ continue; \
++ else
++
++/* Iterate over all used channels with interrupts */
++#define efx_for_each_channel_with_interrupt(_channel, _efx) \
++ for (_channel = &_efx->channel[0]; \
++ _channel < &_efx->channel[EFX_MAX_CHANNELS]; \
++ _channel++) \
++ if (!(_channel->used_flags && _channel->has_interrupt)) \
++ continue; \
++ else
++
++/* Iterate over all used TX queues */
++#define efx_for_each_tx_queue(_tx_queue, _efx) \
++ for (_tx_queue = &_efx->tx_queue[0]; \
++ _tx_queue < &_efx->tx_queue[EFX_MAX_TX_QUEUES]; \
++ _tx_queue++) \
++ if (!_tx_queue->used) \
++ continue; \
++ else
++
++/* Iterate over all TX queues belonging to a channel */
++#define efx_for_each_channel_tx_queue(_tx_queue, _channel) \
++ for (_tx_queue = &_channel->efx->tx_queue[0]; \
++ _tx_queue < &_channel->efx->tx_queue[EFX_MAX_TX_QUEUES]; \
++ _tx_queue++) \
++ if ((!_tx_queue->used) || \
++ (_tx_queue->channel != _channel)) \
++ continue; \
++ else
++
++/* Iterate over all used RX queues */
++#define efx_for_each_rx_queue(_rx_queue, _efx) \
++ for (_rx_queue = &_efx->rx_queue[0]; \
++ _rx_queue < &_efx->rx_queue[EFX_MAX_RX_QUEUES]; \
++ _rx_queue++) \
++ if (!_rx_queue->used) \
++ continue; \
++ else
++
++/* Iterate over all RX queues belonging to a channel */
++#define efx_for_each_channel_rx_queue(_rx_queue, _channel) \
++ for (_rx_queue = &_channel->efx->rx_queue[0]; \
++ _rx_queue < &_channel->efx->rx_queue[EFX_MAX_RX_QUEUES]; \
++ _rx_queue++) \
++ if ((!_rx_queue->used) || \
++ (_rx_queue->channel != _channel)) \
++ continue; \
++ else
++
++/* Name formats */
++#define EFX_CHANNEL_NAME(_channel) "channel%d", _channel->channel
++#define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue
++#define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue
++
++/* Returns a pointer to the specified receive buffer in the RX
++ * descriptor queue.
++ */
++static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
++ unsigned int index)
++{
++ return (&rx_queue->buffer[index]);
++}
++
++/* Set bit in a little-endian bitfield */
++static inline void set_bit_le(int nr, unsigned char *addr)
++{
++ addr[nr / 8] |= (1 << (nr % 8));
++}
++
++/* Clear bit in a little-endian bitfield */
++static inline void clear_bit_le(int nr, unsigned char *addr)
++{
++ addr[nr / 8] &= ~(1 << (nr % 8));
++}
++
++
++/**
++ * EFX_MAX_FRAME_LEN - calculate maximum frame length
++ *
++ * This calculates the maximum frame length that will be used for a
++ * given MTU. The frame length will be equal to the MTU plus a
++ * constant amount of header space and padding. This is the quantity
++ * that the net driver will program into the MAC as the maximum frame
++ * length.
++ *
++ * The 10G MAC used in Falcon requires 8-byte alignment on the frame
++ * length, so we round up to the nearest 8.
++ */
++#define EFX_MAX_FRAME_LEN(mtu) \
++ ((((mtu) + ETH_HLEN + VLAN_HLEN + 4/* FCS */) + 7) & ~7)
++
++
++#endif /* EFX_NET_DRIVER_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/null_phy.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/null_phy.c
+--- linux-2.6.18.8/drivers/net/sfc/null_phy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/null_phy.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,62 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "efx.h"
++#include "falcon.h"
++#include "gmii.h"
++#include "phy.h"
++
++static int falcon_null_phy_check_hw(struct efx_nic *efx)
++{
++ int link_ok = falcon_xaui_link_ok(efx);
++
++ /* Generate PHY event that a PHY would have generated */
++ if (link_ok != efx->link_up) {
++ efx->link_up = link_ok;
++ efx->mac_op->fake_phy_event(efx);
++ }
++
++ return 0;
++}
++
++static void falcon_null_phy_reconfigure(struct efx_nic *efx)
++{
++ /* CX4 is always 10000FD only */
++ efx->link_options = GM_LPA_10000FULL;
++
++ falcon_null_phy_check_hw(efx);
++}
++
++struct efx_phy_operations falcon_null_phy_ops = {
++ .reconfigure = falcon_null_phy_reconfigure,
++ .check_hw = falcon_null_phy_check_hw,
++ .fini = efx_port_dummy_op_void,
++ .clear_interrupt = efx_port_dummy_op_void,
++ .init = efx_port_dummy_op_int,
++ .reset_xaui = efx_port_dummy_op_void,
++ .mmds = 0,
++ .loopbacks = 0,
++ .startup_loopback = 0,
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/phy.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/phy.c
+--- linux-2.6.18.8/drivers/net/sfc/phy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/phy.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,28 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "net_driver.h"
++#include "phy.h"
++
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/phy.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/phy.h
+--- linux-2.6.18.8/drivers/net/sfc/phy.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/phy.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,90 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_PHY_H
++#define EFX_PHY_H
++
++/****************************************************************************
++ * 10Xpress (SFX7101) PHY
++ */
++extern struct efx_phy_operations falcon_tenxpress_phy_ops;
++
++enum tenxpress_state {
++ TENXPRESS_STATUS_OFF = 0,
++ TENXPRESS_STATUS_OTEMP = 1,
++ TENXPRESS_STATUS_NORMAL = 2,
++};
++
++extern void tenxpress_set_state(struct efx_nic *efx,
++ enum tenxpress_state state);
++extern void tenxpress_phy_blink(struct efx_nic *efx, int blink);
++extern void tenxpress_crc_err(struct efx_nic *efx);
++
++/****************************************************************************
++ * Marvell 88E1111 "Alaska" PHY control
++ */
++extern struct efx_phy_operations alaska_phy_operations;
++
++/****************************************************************************
++* Exported functions from the driver for Transwitch CX4 retimer
++*/
++extern struct efx_phy_operations falcon_txc_phy_ops;
++
++#define TXC_GPIO_DIR_INPUT (0)
++#define TXC_GPIO_DIR_OUTPUT (1)
++
++extern void txc_set_gpio_dir(struct efx_nic *p, int pin, int dir);
++extern void txc_set_gpio_val(struct efx_nic *p, int pin, int val);
++
++/****************************************************************************
++ * Exported functions from the driver for PMC PM8358 PHY
++ */
++extern struct efx_phy_operations falcon_pm8358_phy_ops;
++
++/****************************************************************************
++ * Exported functions from the driver for XFP optical PHYs
++ */
++extern struct efx_phy_operations falcon_xfp_phy_ops;
++
++/* The QUAKE XFP PHY provides various H/W control states for LEDs */
++#define QUAKE_LED_LINK_INVAL (0)
++#define QUAKE_LED_LINK_STAT (1)
++#define QUAKE_LED_LINK_ACT (2)
++#define QUAKE_LED_LINK_ACTSTAT (3)
++#define QUAKE_LED_OFF (4)
++#define QUAKE_LED_ON (5)
++#define QUAKE_LED_LINK_INPUT (6) /* Pin is an input. */
++/* What link the LED tracks */
++#define QUAKE_LED_TXLINK (0)
++#define QUAKE_LED_RXLINK (8)
++
++extern void xfp_set_led(struct efx_nic *p, int led, int state);
++
++/****************************************************************************
++ * NULL PHY ops
++ */
++extern struct efx_phy_operations falcon_null_phy_ops;
++
++#endif
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/pm8358_phy.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/pm8358_phy.c
+--- linux-2.6.18.8/drivers/net/sfc/pm8358_phy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/pm8358_phy.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,206 @@
++/* Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++/*
++ * Driver for PMC-Sierra PM8358 XAUI PHY
++ */
++
++#include <linux/delay.h>
++#include "efx.h"
++#include "gmii.h"
++#include "mdio_10g.h"
++#include "phy.h"
++
++#define PM8358_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_DTEXS)
++#define PM8358_LOOPBACKS (1 << LOOPBACK_PHY)
++
++/* PHY-specific definitions */
++/* Master ID and Global Performance Monitor Update */
++#define PMC_MASTER_REG (0xd000)
++/* Analog TX/RX settings under software control */
++#define PMC_MASTER_ANLG_CTRL (1 << 11)
++
++#define PMC_MCONF2_REG (0xd002)
++/* Drive TX off centre of data eye (1) vs. clock edge (0) */
++#define PMC_MCONF2_TEDGE (1 << 2)
++/* Drive RX off centre of data eye (1) vs. clock edge (0) */
++#define PMC_MCONF2_REDGE (1 << 3)
++
++/* Analog RX settings */
++#define PMC_ANALOG_RX_CFG0 (0xd025)
++#define PMC_ANALOG_RX_CFG1 (0xd02d)
++#define PMC_ANALOG_RX_CFG2 (0xd035)
++#define PMC_ANALOG_RX_CFG3 (0xd03d)
++#define PMC_ANALOG_RX_TERM (1 << 15) /* Bit 15 of RX CFG: 0 for 100 ohms
++ float, 1 for 50 to 1.2V */
++#define PMC_ANALOG_RX_EQ_MASK (3 << 8)
++#define PMC_ANALOG_RX_EQ_NONE (0 << 8)
++#define PMC_ANALOG_RX_EQ_HALF (1 << 8)
++#define PMC_ANALOG_RX_EQ_FULL (2 << 8)
++#define PMC_ANALOG_RX_EQ_RSVD (3 << 8)
++
++/* Reset the DTE XS MMD. */
++#define PMC_MAX_RESET_TIME 500
++#define PMC_RESET_WAIT 10
++
++static int pmc_reset_phy(struct efx_nic *efx)
++{
++ int rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_DTEXS,
++ PMC_MAX_RESET_TIME / PMC_RESET_WAIT,
++ PMC_RESET_WAIT);
++ if (rc >= 0) {
++ EFX_TRACE(efx, "PMC8358: came out of reset with "
++ "%d0 ms left\n", rc);
++ rc = 0;
++ } else {
++ EFX_ERR(efx, "PMC8358: reset timed out!\n");
++ }
++ return rc;
++}
++
++
++static void pmc_full_rx_eq(struct efx_nic *efx)
++{
++ int i, reg;
++
++ /* Enable software control of analog settings */
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_DTEXS, PMC_MASTER_REG);
++ reg |= PMC_MASTER_ANLG_CTRL;
++
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ MDIO_MMD_DTEXS, PMC_MASTER_REG, reg);
++
++ /* Turn RX eq on full for all channels. */
++ for (i = 0; i < 3; i++) {
++ /* The analog CFG registers are evenly spaced 8 apart */
++ u16 addr = PMC_ANALOG_RX_CFG0 + 8 * i;
++
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_DTEXS, addr);
++ reg = (reg & ~PMC_ANALOG_RX_EQ_MASK) | PMC_ANALOG_RX_EQ_FULL;
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ MDIO_MMD_DTEXS, addr, reg);
++ }
++}
++
++static void pmc_set_data_edges(struct efx_nic *efx)
++{
++ int reg;
++ /* Set TEDGE, clear REDGE */
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_DTEXS, PMC_MCONF2_REG);
++ reg &= ~PMC_MCONF2_REDGE;
++ reg |= PMC_MCONF2_TEDGE;
++
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ MDIO_MMD_DTEXS, PMC_MCONF2_REG, reg);
++}
++
++static int pm8358_phy_init(struct efx_nic *efx)
++{
++ u32 devid;
++ int rc;
++
++ /* The GLB_CTL reset line has been pulled before this is called,
++ * and it may take up to 5ms for the PLL's to synchronise after
++ * this is done. Best to wait 10ms here */
++ schedule_timeout_uninterruptible(HZ / 100);
++
++ rc = pmc_reset_phy(efx);
++ if (rc < 0)
++ return rc;
++
++ /* Check that all the MMDs we expect are present and responding. We
++ * expect faults on some if the link is down, but not on the PHY XS */
++ rc = mdio_clause45_check_mmds(efx, PM8358_REQUIRED_DEVS, 0);
++ if (rc < 0)
++ return rc;
++
++ devid = mdio_clause45_read_id(efx, MDIO_MMD_DTEXS);
++ EFX_LOG(efx, "PM8358: PHY ID reg %x (OUI %x model %x revision"
++ " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid),
++ MDIO_ID_REV(devid));
++
++ /* Turn on full RX equalisation */
++ pmc_full_rx_eq(efx);
++
++ /* Adjust RX and TX data edge position */
++ pmc_set_data_edges(efx);
++
++ EFX_LOG(efx, "PM8358: PHY init successful.\n");
++ return rc;
++}
++
++static int pm8358_link_ok(struct efx_nic *efx)
++{
++ return mdio_clause45_links_ok(efx, PM8358_REQUIRED_DEVS);
++}
++
++static int pm8358_phy_check_hw(struct efx_nic *efx)
++{
++ int rc = 0;
++ int link_up = pm8358_link_ok(efx);
++ /* Simulate a PHY event if link state has changed */
++ if (link_up != efx->link_up) {
++ efx->link_up = link_up;
++ efx->mac_op->fake_phy_event(efx);
++ }
++
++ return rc;
++}
++
++static void pm8358_phy_reconfigure(struct efx_nic *efx)
++{
++ int phy_id = efx->mii.phy_id;
++ int ctrl;
++ /* Handle DTE loopback */
++ ctrl = mdio_clause45_read(efx, phy_id, MDIO_MMD_DTEXS,
++ MDIO_MMDREG_CTRL1);
++ if (efx->loopback_mode == LOOPBACK_PHY) {
++ EFX_TRACE(efx, "PM8358: setting DTE loopback\n");
++ ctrl |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
++ } else {
++ if (ctrl & (1 << MDIO_MMDREG_CTRL1_LBACK_LBN))
++ EFX_TRACE(efx,
++ "PM8358: clearing DTE loopback\n");
++ ctrl &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
++ }
++ mdio_clause45_write(efx, phy_id, MDIO_MMD_DTEXS,
++ MDIO_MMDREG_CTRL1, ctrl);
++
++ efx->link_up = pm8358_link_ok(efx);
++ efx->link_options = GM_LPA_10000FULL;
++}
++
++struct efx_phy_operations falcon_pm8358_phy_ops = {
++ .init = pm8358_phy_init,
++ .reconfigure = pm8358_phy_reconfigure,
++ .check_hw = pm8358_phy_check_hw,
++ .fini = efx_port_dummy_op_void,
++ .clear_interrupt = efx_port_dummy_op_void,
++ .reset_xaui = efx_port_dummy_op_void,
++ .mmds = PM8358_REQUIRED_DEVS,
++ .loopbacks = PM8358_LOOPBACKS,
++ .startup_loopback = LOOPBACK_PHY,
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/rx.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/rx.c
+--- linux-2.6.18.8/drivers/net/sfc/rx.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/rx.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,798 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <net/ip.h>
++#include <net/checksum.h>
++#include "net_driver.h"
++#include "rx.h"
++#include "efx.h"
++#include "falcon.h"
++#include "selftest.h"
++#include "workarounds.h"
++
++
++/* Number of RX descriptors pushed at once. */
++#define EFX_RX_BATCH 8
++
++/* Size of buffer allocated for skb header area. */
++#define EFX_SKB_HEADERS 64u
++
++/*
++ * rx_alloc_method - RX buffer allocation method
++ *
++ * This driver supports two methods for allocating and using RX buffers:
++ * each RX buffer may be backed by an skb or by an order-n page.
++ *
++ * When LRO is in use then the second method has a lower overhead,
++ * since we don't have to allocate then free skbs on reassembled frames.
++ *
++ * Values:
++ * - RX_ALLOC_METHOD_AUTO = 0
++ * - RX_ALLOC_METHOD_SKB = 1
++ * - RX_ALLOC_METHOD_PAGE = 2
++ *
++ * The heuristic for %RX_ALLOC_METHOD_AUTO is a simple hysteresis count
++ * controlled by the parameters below.
++ *
++ * - Since pushing and popping descriptors are separated by the rx_queue
++ * size, so the watermarks should be ~rxd_size.
++ * - The performance win by using page-based allocation for LRO is less
++ * than the performance hit of using page-based allocation of non-LRO,
++ * so the watermarks should reflect this.
++ *
++ * Per channel we maintain a single variable, updated by each channel:
++ *
++ * rx_alloc_level += (lro_performed ? RX_ALLOC_FACTOR_LRO :
++ * RX_ALLOC_FACTOR_SKB)
++ * Per NAPI poll interval, we constrain rx_alloc_level to 0..MAX (which
++ * limits the hysteresis), and update the allocation strategy:
++ *
++ * rx_alloc_method = (rx_alloc_level > RX_ALLOC_LEVEL_LRO ?
++ * RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB)
++ */
++static int rx_alloc_method = RX_ALLOC_METHOD_PAGE;
++
++#define RX_ALLOC_LEVEL_LRO 0x2000
++#define RX_ALLOC_LEVEL_MAX 0x3000
++#define RX_ALLOC_FACTOR_LRO 1
++#define RX_ALLOC_FACTOR_SKB -2
++
++/* This is the percentage fill level below which new RX descriptors
++ * will be added to the RX descriptor ring.
++ */
++static unsigned int rx_refill_threshold = 90;
++
++/* This is the percentage fill level to which an RX queue will be refilled
++ * when the "RX refill threshold" is reached.
++ */
++static unsigned int rx_refill_limit = 95;
++
++/*
++ * RX maximum head room required.
++ *
++ * This must be at least 1 to prevent overflow and at least 2 to allow
++ * pipelined receives.
++ */
++#define EFX_RXD_HEAD_ROOM 2
++
++/* Macros for zero-order pages (potentially) containing multiple RX buffers */
++#define RX_DATA_OFFSET(_data) \
++ (((unsigned long) (_data)) & (PAGE_SIZE-1))
++#define RX_BUF_OFFSET(_rx_buf) \
++ RX_DATA_OFFSET((_rx_buf)->data)
++
++#define RX_PAGE_SIZE(_efx) \
++ (PAGE_SIZE * (1u << (_efx)->rx_buffer_order))
++
++
++/**
++ * efx_init_rx_buffer_skb - create new RX buffer using skb-based allocation
++ *
++ * @rx_queue: Efx RX queue
++ * @rx_buf: RX buffer structure to populate
++ *
++ * This allocates memory for a new receive buffer, maps it for DMA,
++ * and populates a struct efx_rx_buffer with the relevant
++ * information. Return a negative error code or 0 on success.
++ */
++static inline int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ struct net_device *net_dev = efx->net_dev;
++ int skb_len = efx->rx_buffer_len;
++
++ rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
++ if (unlikely(!rx_buf->skb))
++ return -ENOMEM;
++
++ /* Adjust the SKB for padding and checksum */
++ skb_reserve(rx_buf->skb, NET_IP_ALIGN);
++ rx_buf->len = skb_len - NET_IP_ALIGN;
++ rx_buf->data = (char *)rx_buf->skb->data;
++
++ rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ /* Map for DMA */
++ rx_buf->dma_addr = pci_map_single(efx->pci_dev,
++ rx_buf->data, rx_buf->len,
++ PCI_DMA_FROMDEVICE);
++
++ if (unlikely(pci_dma_mapping_error(rx_buf->dma_addr))) {
++ /* Free the SKB */
++ dev_kfree_skb_any(rx_buf->skb);
++ rx_buf->skb = NULL;
++ return -EIO;
++ }
++
++ return 0;
++}
++
++/**
++ * efx_init_rx_buffer_page - create new RX buffer using page-based allocation
++ *
++ * @rx_queue: Efx RX queue
++ * @rx_buf: RX buffer structure to populate
++ *
++ * This allocates memory for a new receive buffer, maps it for DMA,
++ * and populates a struct efx_rx_buffer with the relevant
++ * information. Return a negative error code or 0 on success.
++ */
++static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ int bytes, space, offset;
++
++ bytes = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
++
++ /* If there is space left in the previously allocated page,
++ * then use it. Otherwise allocate a new one */
++ rx_buf->page = rx_queue->buf_page;
++ if (rx_buf->page == NULL) {
++ dma_addr_t dma_addr;
++
++ rx_buf->page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC,
++ efx->rx_buffer_order);
++ if (unlikely(rx_buf->page == NULL))
++ return -ENOMEM;
++
++ /* Map the entire page for DMA */
++ dma_addr = pci_map_page(efx->pci_dev, rx_buf->page,
++ 0, RX_PAGE_SIZE(efx),
++ PCI_DMA_FROMDEVICE);
++
++ if (unlikely(pci_dma_mapping_error(dma_addr))) {
++ __free_pages(rx_buf->page, efx->rx_buffer_order);
++ rx_buf->page = NULL;
++ return -EIO;
++ }
++
++ rx_queue->buf_page = rx_buf->page;
++ rx_queue->buf_dma_addr = dma_addr;
++ rx_queue->buf_data = ((char *) page_address(rx_buf->page) +
++ EFX_PAGE_IP_ALIGN);
++ }
++
++ offset = RX_DATA_OFFSET(rx_queue->buf_data);
++ rx_buf->len = bytes;
++ rx_buf->dma_addr = rx_queue->buf_dma_addr + offset;
++ rx_buf->data = rx_queue->buf_data;
++
++ /* Try to pack multiple buffers per page */
++ if (efx->rx_buffer_order == 0) {
++ /* The next buffer starts on the next 512 byte boundary */
++ rx_queue->buf_data += ((bytes + 0x1ff) & ~0x1ff);
++ offset += ((bytes + 0x1ff) & ~0x1ff);
++
++ space = RX_PAGE_SIZE(efx) - offset;
++ if (space >= bytes) {
++ /* Refs dropped on kernel releasing each skb */
++ get_page(rx_queue->buf_page);
++ goto out;
++ }
++ }
++
++ /* This is the final RX buffer for this page, so mark it for
++ * unmapping */
++ rx_queue->buf_page = NULL;
++ rx_buf->unmap_addr = rx_queue->buf_dma_addr;
++
++ out:
++ return 0;
++}
++
++/* This allocates memory for a new receive buffer, maps it for DMA,
++ * and populates a struct efx_rx_buffer with the relevant
++ * information.
++ */
++static inline int efx_init_rx_buffer(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *new_rx_buf)
++{
++ int rc = 0;
++
++ if (rx_queue->channel->rx_alloc_push_pages) {
++ new_rx_buf->skb = NULL;
++ rc = efx_init_rx_buffer_page(rx_queue, new_rx_buf);
++ rx_queue->alloc_page_count++;
++ } else {
++ new_rx_buf->page = NULL;
++ rc = efx_init_rx_buffer_skb(rx_queue, new_rx_buf);
++ rx_queue->alloc_skb_count++;
++ }
++
++ if (unlikely(rc < 0))
++ EFX_LOG_RL(rx_queue->efx, "%s RXQ[%d] =%d\n", __func__,
++ rx_queue->queue, rc);
++ return rc;
++}
++
++static inline void efx_unmap_rx_buffer(struct efx_nic *efx,
++ struct efx_rx_buffer *rx_buf)
++{
++ if (rx_buf->page) {
++ EFX_BUG_ON_PARANOID(rx_buf->skb);
++ if (rx_buf->unmap_addr) {
++ pci_unmap_page(efx->pci_dev, rx_buf->unmap_addr,
++ RX_PAGE_SIZE(efx), PCI_DMA_FROMDEVICE);
++ rx_buf->unmap_addr = 0;
++ }
++ } else if (likely(rx_buf->skb)) {
++ pci_unmap_single(efx->pci_dev, rx_buf->dma_addr,
++ rx_buf->len, PCI_DMA_FROMDEVICE);
++ }
++}
++
++static inline void efx_free_rx_buffer(struct efx_nic *efx,
++ struct efx_rx_buffer *rx_buf)
++{
++ if (rx_buf->page) {
++ __free_pages(rx_buf->page, efx->rx_buffer_order);
++ rx_buf->page = NULL;
++ } else if (likely(rx_buf->skb)) {
++ dev_kfree_skb_any(rx_buf->skb);
++ rx_buf->skb = NULL;
++ }
++}
++
++inline void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf)
++{
++ /* Unmap for DMA */
++ efx_unmap_rx_buffer(rx_queue->efx, rx_buf);
++
++ /* Free the skb/page */
++ efx_free_rx_buffer(rx_queue->efx, rx_buf);
++}
++
++/**
++ * efx_fast_push_rx_descriptors - push new RX descriptors quickly
++ * @rx_queue: RX descriptor queue
++ * @retry: Recheck the fill level
++ * This will aim to fill the RX descriptor queue up to
++ * @rx_queue->@fast_fill_limit. If there is insufficient atomic
++ * memory to do so, the caller should retry.
++ */
++static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue,
++ int retry)
++{
++ struct efx_rx_buffer *rx_buf;
++ unsigned fill_level, index;
++ int i, space, rc = 0;
++
++ /* Calculate current fill level. Do this outside the lock,
++ * because most of the time we'll end up not wanting to do the
++ * fill anyway.
++ */
++ fill_level = (rx_queue->added_count - rx_queue->removed_count);
++ EFX_BUG_ON_PARANOID(fill_level >
++ rx_queue->efx->type->rxd_ring_mask + 1);
++
++ /* Don't fill if we don't need to */
++ if (fill_level >= rx_queue->fast_fill_trigger)
++ return 0;
++
++ /* Record minimum fill level */
++ if (unlikely(fill_level < rx_queue->min_fill))
++ if (fill_level)
++ rx_queue->min_fill = fill_level;
++
++ /* Acquire RX add lock. If this lock is contended, then a fast
++ * fill must already be in progress (e.g. in the refill
++ * tasklet), so we don't need to do anything
++ */
++ if (!spin_trylock_bh(&rx_queue->add_lock))
++ return -1;
++
++ retry:
++ /* Recalculate current fill level now that we have the lock */
++ fill_level = (rx_queue->added_count - rx_queue->removed_count);
++ EFX_BUG_ON_PARANOID(fill_level >
++ rx_queue->efx->type->rxd_ring_mask + 1);
++ space = rx_queue->fast_fill_limit - fill_level;
++ if (space < EFX_RX_BATCH)
++ goto out_unlock;
++
++ EFX_TRACE(rx_queue->efx, "RX queue %d fast-filling descriptor ring from"
++ " level %d to level %d using %s allocation\n",
++ rx_queue->queue, fill_level, rx_queue->fast_fill_limit,
++ rx_queue->channel->rx_alloc_push_pages ? "page" : "skb");
++
++ do {
++ for (i = 0; i < EFX_RX_BATCH; ++i) {
++ index = (rx_queue->added_count &
++ rx_queue->efx->type->rxd_ring_mask);
++ rx_buf = efx_rx_buffer(rx_queue, index);
++ rc = efx_init_rx_buffer(rx_queue, rx_buf);
++ if (unlikely(rc))
++ goto out;
++ ++rx_queue->added_count;
++ }
++ } while ((space -= EFX_RX_BATCH) >= EFX_RX_BATCH);
++
++ EFX_TRACE(rx_queue->efx, "RX queue %d fast-filled descriptor ring "
++ "to level %d\n", rx_queue->queue,
++ rx_queue->added_count - rx_queue->removed_count);
++
++ out:
++ /* Send write pointer to card. */
++ falcon_notify_rx_desc(rx_queue);
++
++ /* If the fast fill is running inside from the refill tasklet, then
++ * for SMP systems it may be running on a different CPU to
++ * RX event processing, which means that the fill level may now be
++ * out of date. */
++ if (unlikely(retry && (rc == 0)))
++ goto retry;
++
++ out_unlock:
++ /* Release RX add lock */
++ spin_unlock_bh(&rx_queue->add_lock);
++
++ return rc;
++}
++
++/**
++ * efx_fast_push_rx_descriptors - push new RX descriptors quickly
++ * @rx_queue: RX descriptor queue
++ *
++ * This will aim to fill the RX descriptor queue up to
++ * @rx_queue->@fast_fill_limit. If there is insufficient memory to do so,
++ * it will schedule a work item to immediately continue the fast fill
++ */
++void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
++{
++ int rc;
++
++ rc = __efx_fast_push_rx_descriptors(rx_queue, 0);
++ if (unlikely(rc)) {
++ /* Schedule the work item to run immediately. The hope is
++ * that work is immediately pending to free some memory
++ * (e.g. an RX event or TX completion)
++ */
++ queue_delayed_work(rx_queue->efx->refill_workqueue,
++ &rx_queue->work, 0);
++ }
++}
++
++void efx_rx_work(struct work_struct *data)
++{
++ struct efx_rx_queue *rx_queue;
++ int rc;
++
++#if !defined(EFX_NEED_WORK_API_WRAPPERS)
++ rx_queue = container_of(data, struct efx_rx_queue, work.work);
++#else
++ rx_queue = container_of(data, struct efx_rx_queue, work);
++#endif
++
++ if (unlikely(!rx_queue->channel->enabled))
++ return;
++
++ EFX_TRACE(rx_queue->efx, "RX queue %d worker thread executing on CPU "
++ "%d\n", rx_queue->queue, raw_smp_processor_id());
++
++ ++rx_queue->slow_fill_count;
++ /* Push new RX descriptors, allowing at least 1 jiffy for
++ * the kernel to free some more memory. */
++ rc = __efx_fast_push_rx_descriptors(rx_queue, 1);
++ if (rc) {
++ queue_delayed_work(rx_queue->efx->refill_workqueue,
++ &rx_queue->work, 1);
++ }
++}
++
++static inline void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
++ struct efx_rx_buffer *rx_buf,
++ int len, int *discard,
++ int *leak_packet)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned max_len = rx_buf->len - efx->type->rx_buffer_padding;
++
++ if (likely(len <= max_len))
++ return;
++
++ /* The packet must be discarded, but this is only a fatal error
++ * if the caller indicated it was
++ */
++ *discard = 1;
++
++ if ((len > rx_buf->len) && EFX_WORKAROUND_8071(efx)) {
++ EFX_ERR_RL(efx, " RX queue %d seriously overlength "
++ "RX event (0x%x > 0x%x+0x%x). Leaking\n",
++ rx_queue->queue, len, max_len,
++ efx->type->rx_buffer_padding);
++ /* If this buffer was skb-allocated, then the meta
++ * data at the end of the skb will be trashed. So
++ * we have no choice but to leak the fragment.
++ */
++ *leak_packet = (rx_buf->skb != NULL);
++ efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
++ } else {
++ EFX_ERR_RL(efx, " RX queue %d overlength RX event "
++ "(0x%x > 0x%x)\n", rx_queue->queue, len, max_len);
++ }
++
++ rx_queue->channel->n_rx_overlength++;
++}
++
++/* Allocate and construct an SKB around a struct page.*/
++static inline struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf,
++ struct efx_nic *efx,
++ int hdr_len)
++{
++ struct sk_buff *skb;
++
++ /* Allocate an SKB to store the headers */
++ skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN);
++ if (unlikely(skb == NULL)) {
++ EFX_ERR_RL(efx, "RX out of memory for skb\n");
++ return NULL;
++ }
++
++ EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags);
++ EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
++
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ skb_reserve(skb, EFX_PAGE_SKB_ALIGN);
++
++ skb->len = rx_buf->len;
++ skb->truesize = rx_buf->len + sizeof(struct sk_buff);
++ memcpy(skb->data, rx_buf->data, hdr_len);
++ skb->tail += hdr_len;
++
++ /* Append the remaining page onto the frag list */
++ if (unlikely(rx_buf->len > hdr_len)) {
++ struct skb_frag_struct *frag = skb_shinfo(skb)->frags;
++ frag->page = rx_buf->page;
++ frag->page_offset = RX_BUF_OFFSET(rx_buf) + hdr_len;
++ frag->size = skb->len - hdr_len;
++ skb_shinfo(skb)->nr_frags = 1;
++ skb->data_len = frag->size;
++ } else {
++ __free_pages(rx_buf->page, efx->rx_buffer_order);
++ skb->data_len = 0;
++ }
++
++ /* Ownership has transferred from the rx_buf to skb */
++ rx_buf->page = NULL;
++
++ /* Move past the ethernet header */
++ skb->protocol = eth_type_trans(skb, efx->net_dev);
++
++ return skb;
++}
++
++#if defined(EFX_USE_FASTCALL)
++void fastcall efx_rx_packet(struct efx_rx_queue *rx_queue,
++ unsigned int index, unsigned int len,
++ int checksummed, int discard)
++#else
++void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
++ unsigned int len, int checksummed, int discard)
++#endif
++{
++ struct efx_nic *efx = rx_queue->efx;
++ struct efx_rx_buffer *rx_buf;
++ int leak_packet = 0;
++
++ rx_buf = efx_rx_buffer(rx_queue, index);
++ EFX_BUG_ON_PARANOID(!rx_buf->data);
++ EFX_BUG_ON_PARANOID(rx_buf->skb && rx_buf->page);
++ EFX_BUG_ON_PARANOID(!(rx_buf->skb || rx_buf->page));
++
++ /* This allows the refill path to post another buffer.
++ * EFX_RXD_HEAD_ROOM ensures that the slot we are using
++ * isn't overwritten yet.
++ */
++ rx_queue->removed_count++;
++
++ /* Validate the length encoded in the event vs the descriptor pushed */
++ efx_rx_packet__check_len(rx_queue, rx_buf, len,
++ &discard, &leak_packet);
++
++ EFX_TRACE(efx, "RX queue %d received id %x at %llx+%x %s%s\n",
++ rx_queue->queue, index,
++ (unsigned long long)rx_buf->dma_addr, len,
++ (checksummed ? " [SUMMED]" : ""),
++ (discard ? " [DISCARD]" : ""));
++
++ /* Discard packet, if instructed to do so */
++ if (unlikely(discard)) {
++ if (unlikely(leak_packet))
++ rx_queue->channel->n_skbuff_leaks++;
++ else
++ /* We haven't called efx_unmap_rx_buffer yet,
++ * so fini the entire rx_buffer here */
++ efx_fini_rx_buffer(rx_queue, rx_buf);
++ return;
++ }
++
++ /* Release card resources - assumes all RX buffers consumed in-order
++ * per RX queue
++ */
++ efx_unmap_rx_buffer(efx, rx_buf);
++
++ /* Prefetch nice and early so data will (hopefully) be in cache by
++ * the time we look at it.
++ */
++ prefetch(rx_buf->data);
++
++ /* Pipeline receives so that we give time for packet headers to be
++ * prefetched into cache.
++ */
++ rx_buf->len = len;
++ if (rx_queue->channel->rx_pkt)
++ __efx_rx_packet(rx_queue->channel,
++ rx_queue->channel->rx_pkt,
++ rx_queue->channel->rx_pkt_csummed);
++ rx_queue->channel->rx_pkt = rx_buf;
++ rx_queue->channel->rx_pkt_csummed = checksummed;
++}
++
++/* Handle a received packet. Second half: Touches packet payload. */
++void __efx_rx_packet(struct efx_channel *channel,
++ struct efx_rx_buffer *rx_buf, int checksummed)
++{
++ struct efx_nic *efx = channel->efx;
++ enum efx_veto veto;
++ struct sk_buff *skb;
++
++ /* If we're in loopback test, then pass the packet directly to the
++ * loopback layer, and free the rx_buf here
++ */
++ if (unlikely(efx->loopback_selftest)) {
++ efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len);
++ efx_free_rx_buffer(efx, rx_buf);
++ goto done;
++ }
++
++ if (rx_buf->skb) {
++ /* Prefetch more information */
++ prefetch(skb_shinfo(rx_buf->skb));
++
++ /* Reserve space for the data */
++ skb_put(rx_buf->skb, rx_buf->len);
++
++ /* Move past the ethernet header. rx_buf->data still points
++ * at the ethernet header */
++ rx_buf->skb->protocol = eth_type_trans(rx_buf->skb,
++ efx->net_dev);
++ }
++
++ /* Both our generic-LRO and SFC-SSR support skb and page based
++ * allocation, but neither support switching from one to the
++ * other on the fly. If we spot that the allocation mode has
++ * changed, then flush the LRO state.
++ */
++ if (unlikely(channel->rx_alloc_pop_pages != (rx_buf->page != NULL))) {
++ channel->rx_alloc_pop_pages = (rx_buf->page != NULL);
++ }
++
++ /* Allow callback to veto the packet */
++ veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len);
++ if (unlikely(veto)) {
++ EFX_LOG(efx, "RX vetoed by driverlink %s driver\n",
++ efx->dl_cb_dev.rx_packet->driver->name);
++ /* Free the buffer now */
++ efx_free_rx_buffer(efx, rx_buf);
++ goto done;
++ }
++
++ /* Form an skb if required */
++ if (rx_buf->page) {
++ int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS);
++ skb = efx_rx_mk_skb(rx_buf, efx, hdr_len);
++ if (unlikely(skb == NULL)) {
++ efx_free_rx_buffer(efx, rx_buf);
++ goto done;
++ }
++ } else {
++ /* We now own the SKB */
++ skb = rx_buf->skb;
++ rx_buf->skb = NULL;
++ }
++
++ EFX_BUG_ON_PARANOID(rx_buf->page);
++ EFX_BUG_ON_PARANOID(rx_buf->skb);
++ EFX_BUG_ON_PARANOID(!skb);
++
++ /* Set the SKB flags */
++ if (unlikely(!checksummed || !efx->rx_checksum_enabled))
++ skb->ip_summed = CHECKSUM_NONE;
++
++ /* Pass the packet up */
++ netif_receive_skb(skb);
++
++ /* Update allocation strategy method */
++ channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
++
++ /* fall-thru */
++done:
++ /* Update statistics */
++ efx->net_dev->last_rx = jiffies;
++}
++
++void efx_rx_strategy(struct efx_channel *channel)
++{
++ enum efx_rx_alloc_method method = rx_alloc_method;
++
++ /* Only makes sense to use page based allocation if LRO is enabled */
++ if (!(channel->efx->net_dev->features & NETIF_F_LRO)) {
++ method = RX_ALLOC_METHOD_SKB;
++ } else if (method == RX_ALLOC_METHOD_AUTO) {
++ /* Constrain the rx_alloc_level */
++ if (channel->rx_alloc_level < 0)
++ channel->rx_alloc_level = 0;
++ else if (channel->rx_alloc_level > RX_ALLOC_LEVEL_MAX)
++ channel->rx_alloc_level = RX_ALLOC_LEVEL_MAX;
++
++ /* Decide on the allocation method */
++ method = ((channel->rx_alloc_level > RX_ALLOC_LEVEL_LRO) ?
++ RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB);
++ }
++
++ /* Push the option */
++ channel->rx_alloc_push_pages = (method == RX_ALLOC_METHOD_PAGE);
++}
++
++int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned int rxq_size;
++ int rc;
++
++ EFX_LOG(efx, "creating RX queue %d\n", rx_queue->queue);
++
++ /* Allocate RX buffers */
++ rxq_size = (efx->type->rxd_ring_mask + 1) * sizeof(*rx_queue->buffer);
++ rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL);
++ if (!rx_queue->buffer) {
++ rc = -ENOMEM;
++ goto fail1;
++ }
++
++ rc = falcon_probe_rx(rx_queue);
++ if (rc)
++ goto fail2;
++
++ return 0;
++
++ fail2:
++ kfree(rx_queue->buffer);
++ rx_queue->buffer = NULL;
++ fail1:
++ /* Mark queue as unused */
++ rx_queue->used = 0;
++
++ return rc;
++}
++
++int efx_init_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ struct efx_nic *efx = rx_queue->efx;
++ unsigned int max_fill, trigger, limit;
++
++ EFX_LOG(rx_queue->efx, "initialising RX queue %d\n", rx_queue->queue);
++
++ ASSERT_RTNL();
++
++ /* Initialise ptr fields */
++ rx_queue->added_count = 0;
++ rx_queue->notified_count = 0;
++ rx_queue->removed_count = 0;
++ rx_queue->min_fill = -1U;
++ rx_queue->min_overfill = -1U;
++
++ /* Initialise limit fields */
++ max_fill = efx->type->rxd_ring_mask + 1 - EFX_RXD_HEAD_ROOM;
++ trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
++ limit = max_fill * min(rx_refill_limit, 100U) / 100U;
++
++ rx_queue->max_fill = max_fill;
++ rx_queue->fast_fill_trigger = trigger;
++ rx_queue->fast_fill_limit = limit;
++
++ /* Set up RX descriptor ring */
++ return falcon_init_rx(rx_queue);
++}
++
++void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ int i;
++ struct efx_rx_buffer *rx_buf;
++
++ EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue);
++
++ ASSERT_RTNL();
++
++ /* Flush RX queue and remove descriptor ring */
++ falcon_fini_rx(rx_queue);
++
++ /* Release RX buffers NB start at index 0 not current HW ptr */
++ if (rx_queue->buffer) {
++ for (i = 0; i <= rx_queue->efx->type->rxd_ring_mask; i++) {
++ rx_buf = efx_rx_buffer(rx_queue, i);
++ efx_fini_rx_buffer(rx_queue, rx_buf);
++ }
++ }
++
++ /* For a page that is part-way through splitting into RX buffers */
++ if (rx_queue->buf_page != NULL) {
++ pci_unmap_page(rx_queue->efx->pci_dev, rx_queue->buf_dma_addr,
++ RX_PAGE_SIZE(rx_queue->efx), PCI_DMA_FROMDEVICE);
++ __free_pages(rx_queue->buf_page,
++ rx_queue->efx->rx_buffer_order);
++ rx_queue->buf_page = NULL;
++ }
++}
++
++void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
++{
++ EFX_LOG(rx_queue->efx, "destroying RX queue %d\n", rx_queue->queue);
++
++ falcon_remove_rx(rx_queue);
++
++ kfree(rx_queue->buffer);
++ rx_queue->buffer = NULL;
++ rx_queue->used = 0;
++}
++
++
++module_param(rx_alloc_method, int, 0644);
++MODULE_PARM_DESC(rx_alloc_method, "Allocation method used for RX buffers");
++
++module_param(rx_refill_threshold, uint, 0444);
++MODULE_PARM_DESC(rx_refill_threshold,
++ "RX descriptor ring fast/slow fill threshold (%)");
++
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/rx.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/rx.h
+--- linux-2.6.18.8/drivers/net/sfc/rx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/rx.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,44 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_RX_H
++#define EFX_RX_H
++
++#include "net_driver.h"
++
++
++int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
++void efx_remove_rx_queue(struct efx_rx_queue *rx_queue);
++int efx_init_rx_queue(struct efx_rx_queue *rx_queue);
++void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
++
++void efx_rx_strategy(struct efx_channel *channel);
++void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
++void efx_rx_work(struct work_struct *data);
++void __efx_rx_packet(struct efx_channel *channel,
++ struct efx_rx_buffer *rx_buf, int checksummed);
++
++
++#endif /* EFX_RX_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/selftest.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/selftest.c
+--- linux-2.6.18.8/drivers/net/sfc/selftest.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/selftest.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,815 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/netdevice.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/kernel_stat.h>
++#include <linux/pci.h>
++#include <linux/ethtool.h>
++#include <linux/ip.h>
++#include <linux/in.h>
++#include <linux/udp.h>
++#include <linux/rtnetlink.h>
++#include <asm/io.h>
++#include "net_driver.h"
++#include "ethtool.h"
++#include "efx.h"
++#include "falcon.h"
++#include "selftest.h"
++#include "boards.h"
++#include "workarounds.h"
++
++/* Self tests */
++
++/*
++ * Loopback test packet structure
++ *
++ * The self-test should stress every RSS vector, and unfortunately
++ * Falcon only performs RSS on TCP/UDP packets.
++ */
++struct efx_loopback_payload {
++ struct ethhdr header;
++ struct iphdr ip;
++ struct udphdr udp;
++ __be16 iteration;
++ const char msg[64];
++} __attribute__ ((packed));
++
++/* Loopback test source MAC address */
++static const unsigned char payload_source[ETH_ALEN] = {
++ 0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b,
++};
++
++static const char *payload_msg =
++ "Hello world! This is an Efx loopback test in progress!";
++
++struct efx_selftest_state {
++ /* Drop all packets in efx_loopback_rx_packet */
++ int flush;
++
++ /* Number of packets being used in this test */
++ int packet_count;
++
++ /* RX good packet count */
++ atomic_t rx_good;
++
++ /* RX bad packet count */
++ atomic_t rx_bad;
++
++ /* Payload used in tests */
++ struct efx_loopback_payload payload;
++};
++
++/**************************************************************************
++ *
++ * Configurable values
++ *
++ **************************************************************************/
++
++/* Level of loopback testing
++ *
++ * The maximum packet burst length is 16**(n-1), i.e.
++ *
++ * - Level 0 : no packets
++ * - Level 1 : 1 packet
++ * - Level 2 : 17 packets (1 * 1 packet, 1 * 16 packets)
++ * - Level 3 : 273 packets (1 * 1 packet, 1 * 16 packet, 1 * 256 packets)
++ *
++ */
++static unsigned int loopback_test_level = 3;
++
++/**************************************************************************
++ *
++ * Interrupt and event queue testing
++ *
++ **************************************************************************/
++
++/*
++ * Test interrupts
++ *
++ * This generates a test interrupt and waits for it to be received by
++ * a CPU. This routine must be called from process context and will
++ * sleep.
++ */
++static int efx_test_interrupts(struct efx_nic *efx,
++ struct efx_self_tests *tests)
++{
++ struct efx_channel *channel;
++ unsigned long j_start;
++
++ EFX_LOG(efx, "testing interrupts\n");
++ tests->interrupt = -1;
++
++ /* Reset interrupt flag */
++ efx->last_irq_cpu = -1;
++ smp_wmb();
++
++ /* To guarantee that an interrupt is received make sure that the
++ * channels are ack'd at least once, reenabling interrupts.
++ * We will then receive an interrupt, either by explicitly
++ * requesting one, or receiving traffic.
++ */
++ efx_for_each_channel_with_interrupt(channel, efx) {
++ /* Process the eventq synchronously */
++ if (channel->work_pending)
++ efx_process_channel_now(channel);
++ /* Check if we haven't already received an interrupt */
++ if (efx->last_irq_cpu >= 0)
++ goto success;
++ }
++
++ j_start = jiffies;
++
++ /* Generate test interrupt. */
++ falcon_generate_interrupt(efx);
++
++ /* Wait for arrival of test interrupt. */
++ EFX_LOG(efx, "waiting for test interrupt\n");
++ schedule_timeout_uninterruptible(HZ / 10);
++ if (efx->last_irq_cpu >= 0)
++ goto success;
++
++ EFX_ERR(efx, "timed out in %ld jiffies waiting for interrupt\n",
++ jiffies - j_start);
++ return -ETIMEDOUT;
++
++ success:
++ EFX_LOG(efx, "%s test interrupt seen on CPU%d\n", INT_MODE(efx),
++ efx->last_irq_cpu);
++ tests->interrupt = 1;
++ return 0;
++}
++
++/*
++ * Test capability of events to receive events
++ * This generates a test event and waits for it to be processed
++ * This routine must be called from process context and will sleep.
++ */
++static int efx_test_eventq(struct efx_channel *channel,
++ struct efx_self_tests *tests)
++{
++ unsigned int magic;
++
++ /* Channel specific code, limited to 20 bits */
++ magic = (0x00010150 + channel->channel);
++ EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n",
++ channel->channel, magic);
++
++ tests->eventq_dma[channel->channel] = -1;
++ tests->eventq_int[channel->channel] = 1; /* fake pass */
++ tests->eventq_poll[channel->channel] = 1; /* fake pass */
++
++ /* Reset flag and zero magic word */
++ channel->efx->last_irq_cpu = -1;
++ channel->eventq_magic = 0;
++ smp_wmb();
++
++ /* Generate test event */
++ falcon_generate_test_event(channel, magic);
++ udelay(1);
++
++ efx_process_channel_now(channel);
++ if (channel->eventq_magic != magic) {
++ EFX_ERR(channel->efx, "channel %d failed to see test event\n",
++ channel->channel);
++ return -ETIMEDOUT;
++ } else {
++ tests->eventq_dma[channel->channel] = 1;
++ }
++
++ return 0;
++}
++
++
++/*
++ * Test capability of events to generate interrupts
++ * This generates a test event and waits for it to be processed by an
++ * ISR. This routine must be called from process context and will
++ * sleep.
++ */
++static int efx_test_eventq_irq(struct efx_channel *channel,
++ struct efx_self_tests *tests)
++{
++ unsigned int magic, count;
++ unsigned long j_start = jiffies;
++
++ /* Channel specific code, limited to 20 bits */
++ magic = (0x00010150 + channel->channel);
++ EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n",
++ channel->channel, magic);
++
++ tests->eventq_dma[channel->channel] = -1;
++ tests->eventq_int[channel->channel] = -1;
++ tests->eventq_poll[channel->channel] = -1;
++
++ /* Reset flag and zero magic word */
++ channel->efx->last_irq_cpu = -1;
++ channel->eventq_magic = 0;
++ smp_wmb();
++
++ /* Generate test event */
++ falcon_generate_test_event(channel, magic);
++
++ /* Wait for arrival of interrupt */
++ count = 0;
++ do {
++ schedule_timeout_uninterruptible(HZ / 100);
++
++ if (channel->work_pending)
++ efx_process_channel_now(channel);
++
++ if (channel->eventq_magic == magic)
++ goto eventq_ok;
++ }
++ while (++count < 2);
++
++ EFX_ERR(channel->efx, "channel %d timed out in %ld jiffies waiting for"
++ " event queue\n", channel->channel, jiffies - j_start);
++
++ /* See if interrupt arrived */
++ if (channel->efx->last_irq_cpu >= 0) {
++ EFX_ERR(channel->efx, "channel %d saw interrupt on CPU%d "
++ "during event queue test\n", channel->channel,
++ raw_smp_processor_id());
++ tests->eventq_int[channel->channel] = 1;
++ }
++
++ /* Check to see if event was received even if interrupt wasn't */
++ efx_process_channel_now(channel);
++ if (channel->eventq_magic == magic) {
++ EFX_ERR(channel->efx, "channel %d event was generated, but "
++ "failed to trigger an interrupt\n", channel->channel);
++ tests->eventq_dma[channel->channel] = 1;
++ }
++
++ return -ETIMEDOUT;
++ eventq_ok:
++ EFX_LOG(channel->efx, "channel %d event queue passed\n",
++ channel->channel);
++ tests->eventq_dma[channel->channel] = 1;
++ tests->eventq_int[channel->channel] = 1;
++ tests->eventq_poll[channel->channel] = 1;
++ return 0;
++}
++
++/**************************************************************************
++ *
++ * PHY testing
++ *
++ **************************************************************************/
++
++/*
++ * Check PHY presence
++ * This reads the PHY ID registers via GMII and checks that neither
++ * are all-zeroes or all-ones (indicating a nonexistent or
++ * uncommunicative PHY).
++ */
++static int efx_test_phy(struct efx_nic *efx,
++ struct efx_self_tests *tests)
++{
++ u16 physid1, physid2;
++ struct mii_if_info *mii = &efx->mii;
++ struct net_device *net_dev = efx->net_dev;
++
++ if (efx->phy_type == PHY_TYPE_NONE)
++ return 0;
++
++ EFX_LOG(efx, "testing PHY presence\n");
++ tests->phy_ok = -1;
++
++ physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1);
++ physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2);
++
++ if ((physid1 != 0x0000) && (physid1 != 0xffff) &&
++ (physid2 != 0x0000) && (physid2 != 0xffff)) {
++ EFX_LOG(efx, "found MII PHY %d ID 0x%x:%x\n",
++ mii->phy_id, physid1, physid2);
++ tests->phy_ok = 1;
++ return 0;
++ }
++
++ EFX_ERR(efx, "no MII PHY present with ID %d\n", mii->phy_id);
++ return -ENODEV;
++}
++
++/**************************************************************************
++ *
++ * Loopback testing
++ * NB Only one loopback test can be executing concurrently.
++ *
++ **************************************************************************/
++
++/* Loopback test RX callback
++ * This is called for each received packet during loopback testing.
++ */
++void efx_loopback_rx_packet(struct efx_nic *efx,
++ const char *buf_ptr, int pkt_len)
++{
++ struct efx_selftest_state *state = efx->loopback_selftest;
++ struct efx_loopback_payload *received;
++ struct efx_loopback_payload *payload;
++
++ BUG_ON(!buf_ptr);
++
++ /* If we are just flushing, then drop the packet */
++ if ((state == NULL) || state->flush)
++ return;
++
++ payload = &state->payload;
++
++ /* The packet should have been passed up to us before any LRO/SSR, so
++ * we should be able to compare the data directly. Since the packet
++ * is going to be thrown away by the caller, modify it in place.
++ * efx_test_loopback guarantees to not touch state->payload during
++ * the test */
++ received = (struct efx_loopback_payload *)(char *)buf_ptr;
++ received->ip.saddr = payload->ip.saddr;
++ received->ip.check = payload->ip.check;
++
++ /* Check that header exists */
++ if (pkt_len < sizeof(received->header)) {
++ EFX_ERR(efx, "saw runt RX packet (length %d) "
++ "in %s loopback test\n", pkt_len,
++ LOOPBACK_MODE(efx));
++ goto err;
++ }
++
++ /* Check that header matches */
++ if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
++ EFX_ERR(efx, "saw non-loopback RX packet in"
++ " %s loopback test\n",
++ LOOPBACK_MODE(efx));
++ goto err;
++ }
++
++ /* Check packet length */
++ if (pkt_len != sizeof(*payload)) {
++ EFX_ERR(efx, "saw incorrect RX packet length"
++ " %d (wanted %d) in %s loopback test\n",
++ pkt_len, (int)sizeof(*payload),
++ LOOPBACK_MODE(efx));
++ goto err;
++ }
++
++ /* Check that IP header matches */
++ if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
++ EFX_ERR(efx, "saw corrupted IP header in %s "
++ "loopback test\n",
++ LOOPBACK_MODE(efx));
++ goto err;
++ }
++
++ /* Check that msg and padding matches */
++ if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
++ EFX_ERR(efx, "saw corrupted RX packet in %s "
++ "loopback test\n",
++ LOOPBACK_MODE(efx));
++ goto err;
++ }
++
++ /* Check that iteration matches */
++ if (received->iteration != payload->iteration) {
++ EFX_ERR(efx, "saw RX packet from iteration %d"
++ " (wanted %d) in %s loopback test\n",
++ ntohs(received->iteration), ntohs(payload->iteration),
++ LOOPBACK_MODE(efx));
++ goto err;
++ }
++
++ /* Increase correct RX count */
++ EFX_TRACE(efx, "got loopback RX in %s loopback test\n",
++ LOOPBACK_MODE(efx));
++
++ atomic_inc(&state->rx_good);
++ return;
++
++ err:
++#ifdef EFX_ENABLE_DEBUG
++ if (atomic_read(&state->rx_bad) == 0) {
++ EFX_ERR(efx, "received packet:\n");
++ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
++ buf_ptr, pkt_len, 0);
++ EFX_ERR(efx, "expected packet:\n");
++ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
++ &state->payload, sizeof(state->payload), 0);
++ }
++#endif
++ atomic_inc(&state->rx_bad);
++}
++
++/* Initialise an efx_selftest_state for a new iteration */
++static void efx_iterate_state(struct efx_nic *efx)
++{
++ struct efx_selftest_state *state = efx->loopback_selftest;
++ struct net_device *net_dev = efx->net_dev;
++ struct efx_loopback_payload *payload = &state->payload;
++
++ /* Initialise the layerII header */
++ memcpy(&payload->header.h_dest, net_dev->dev_addr, ETH_ALEN);
++ memcpy(&payload->header.h_source, &payload_source, ETH_ALEN);
++ payload->header.h_proto = htons(ETH_P_IP);
++
++ /* saddr set later and used as incrementing count */
++ payload->ip.daddr = htonl(INADDR_LOOPBACK);
++ payload->ip.ihl = 5;
++ payload->ip.check = 0; /* offloaded */
++ payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
++ payload->ip.version = IPVERSION;
++ payload->ip.protocol = IPPROTO_UDP;
++
++ /* Initialise udp header */
++ payload->udp.source = 0;
++ payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
++ sizeof(struct iphdr));
++ payload->udp.check = 0; /* checksum ignored */
++
++ /* Fill out payload */
++ payload->iteration = htons(ntohs(payload->iteration) + 1);
++ memcpy(&payload->msg, payload_msg, sizeof(payload_msg));
++
++ /* Fill out remaining state members */
++ atomic_set(&state->rx_good, 0);
++ atomic_set(&state->rx_bad, 0);
++ smp_wmb();
++}
++
++/*
++ * Perform loopback test with N packets
++ *
++ * This will transmit "num_packets" copies of a test packet, and check
++ * that they were both transmitted (i.e. a TX completion event was
++ * received) and received (i.e. the data arrived intact via loopback).
++ * The port must have already been placed into the desired loopback
++ * mode.
++ */
++static int efx_test_loopback(struct efx_nic *efx,
++ struct efx_tx_queue *tx_queue,
++ struct efx_loopback_self_tests *lb_tests)
++{
++#if !defined(EFX_HAVE_OLD_NAPI)
++ struct efx_channel *channel;
++#endif
++ struct efx_selftest_state *state = efx->loopback_selftest;
++ struct efx_loopback_payload *payload;
++ struct sk_buff *skb;
++ int rc = 0, i, tx_done, rx_good, rx_bad;
++
++ /* Fill out the packet contents */
++ efx_iterate_state(efx);
++
++ /* Create and fill skb */
++ skb = alloc_skb(sizeof(state->payload), GFP_KERNEL);
++ if (!skb) {
++ rc = -ENOMEM;
++ goto out1;
++ }
++ payload = ((struct efx_loopback_payload *)
++ skb_put(skb, sizeof(state->payload)));
++ memcpy(payload, &state->payload, sizeof(state->payload));
++
++ /* Transmit N copies of buffer */
++ for (i = 0; i < state->packet_count; i++) {
++ /* Set the source address in the copy of the packet.
++ * Incrementing the source address on a per-packet basis
++ * should ensure that we stress all RSS vectors */
++ payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
++ skb_get(skb);
++
++ if (efx_xmit(efx, tx_queue, skb) != NETDEV_TX_OK) {
++ EFX_ERR(efx, "TX queue %d could not transmit "
++ "packet %d of %d in %s loopback test\n",
++ tx_queue->queue, i + 1,
++ state->packet_count, LOOPBACK_MODE(efx));
++ rc = -EPIPE;
++ goto out2;
++ }
++
++ /* Avoid hogging the PCI bus */
++ udelay(10);
++ }
++
++#if !defined(EFX_HAVE_OLD_NAPI)
++ /* NAPI polling is not enabled, so process channels synchronously */
++ schedule_timeout_uninterruptible(HZ / 50);
++ efx_for_each_channel_with_interrupt(channel, efx) {
++ if (channel->work_pending)
++ efx_process_channel_now(channel);
++ }
++#else
++ /* Allow time for processing */
++ schedule_timeout_uninterruptible(HZ / 10);
++#endif
++
++ if (state->flush)
++ goto out3;
++
++ /* Check TX completion and received packet counts */
++ tx_done = state->packet_count - (atomic_read(&skb->users) - 1);
++ rx_good = atomic_read(&state->rx_good);
++ rx_bad = atomic_read(&state->rx_bad);
++ if (tx_done != state->packet_count) {
++ /* Don't free the skbs; they will be picked up on TX
++ * overflow or channel teardown.
++ */
++ EFX_ERR(efx, "TX queue %d saw only %d out of an "
++ "expected %d TX completion events in %s loopback "
++ "test\n", tx_queue->queue, tx_done,
++ state->packet_count, LOOPBACK_MODE(efx));
++ rc = -ETIMEDOUT;
++ /* Allow to fall through so we see the RX errors as well */
++ }
++
++ /* We may always be up to a flush away from our desired packet total */
++ if (rx_good != state->packet_count) {
++ EFX_LOG(efx, "TX queue %d saw only %d out of an "
++ "expected %d received packets in %s loopback "
++ "test\n", tx_queue->queue, rx_good,
++ state->packet_count, LOOPBACK_MODE(efx));
++ rc = -ETIMEDOUT;
++ /* Fall through */
++ }
++
++ /* Update loopback test structure */
++ lb_tests->tx_sent[tx_queue->queue] += state->packet_count;
++ lb_tests->tx_done[tx_queue->queue] += tx_done;
++ lb_tests->rx_good += rx_good;
++ lb_tests->rx_bad += rx_bad;
++
++ out3:
++ out2:
++ /* Free skb */
++ if (skb) {
++ /* If the selftest failed then the skb needs its reference
++ * count decreasing */
++ while (skb_shared(skb))
++ kfree_skb(skb);
++ dev_kfree_skb_any(skb);
++ }
++
++ out1:
++ return rc;
++}
++
++/* Perform loopback test safely
++ *
++ * This performs a safe loopback test by starting with a single packet
++ * and only increasing the number of packets while the tests are
++ * passing. This avoids flooding a network with garbage packets if
++ * e.g. setting the loopback mode fails.
++ */
++static int
++efx_test_loopback_safely(struct efx_nic *efx,
++ struct efx_tx_queue *tx_queue,
++ struct efx_loopback_self_tests *lb_tests)
++{
++ struct efx_selftest_state *state = efx->loopback_selftest;
++ int i, rc = 0;
++
++ for (i = 0; i < loopback_test_level; i++) {
++ /* Determine how many packets to send */
++ state->packet_count = (efx->type->txd_ring_mask + 1) / 3;
++ state->packet_count = min(1 << (i << 2), state->packet_count);
++ state->flush = 0;
++
++ EFX_LOG(efx, "TX queue %d testing %s loopback"
++ " with %d packets\n", tx_queue->queue,
++ LOOPBACK_MODE(efx), state->packet_count);
++
++ rc = efx_test_loopback(efx, tx_queue, lb_tests);
++ if (rc) {
++ /* Wait a while to ensure there are no packets
++ * floating around after a failure.
++ */
++ schedule_timeout_uninterruptible(HZ / 5);
++ return rc;
++ }
++ }
++
++ EFX_LOG(efx, "TX queue %d passed %s loopback test "
++ "with a burst length of %d packets\n",
++ tx_queue->queue, LOOPBACK_MODE(efx), state->packet_count);
++
++ return rc;
++}
++
++static int efx_test_loopbacks(struct efx_nic *efx,
++ struct efx_self_tests *tests,
++ unsigned int loopback_modes)
++{
++ struct efx_selftest_state *state = efx->loopback_selftest;
++ struct ethtool_cmd ecmd, ecmd_loopback;
++ struct efx_tx_queue *tx_queue;
++ enum efx_loopback_mode old_mode, mode;
++ int old_powered, count, rc = 0;
++ int retry = EFX_WORKAROUND_8909(efx);
++
++ /* Get current PHY settings */
++ rc = efx_ethtool_get_settings(efx->net_dev, &ecmd);
++ if (rc) {
++ EFX_ERR(efx, "could not get GMII settings\n");
++ return rc;
++ }
++ old_mode = efx->loopback_mode;
++ old_powered = efx->phy_powered;
++
++ /* Disable autonegotiation for the purposes of loopback */
++ memcpy(&ecmd_loopback, &ecmd, sizeof(ecmd_loopback));
++ if (ecmd_loopback.autoneg == AUTONEG_ENABLE) {
++ ecmd_loopback.autoneg = AUTONEG_DISABLE;
++ ecmd_loopback.duplex = DUPLEX_FULL;
++ ecmd_loopback.speed = EFX_IS10G(efx) ?
++ SPEED_10000 : SPEED_1000;
++ }
++
++ rc = efx_ethtool_set_settings(efx->net_dev, &ecmd_loopback);
++ if (rc) {
++ EFX_ERR(efx, "could not disable autonegotiation\n");
++ goto out;
++ }
++ tests->loopback_speed = ecmd_loopback.speed;
++ tests->loopback_full_duplex = ecmd_loopback.duplex;
++
++ /* Test all supported loopback modes */
++ for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) {
++ if (!(loopback_modes & (1 << mode)))
++ continue;
++
++ /* Move the port into the specified loopback mode. */
++ state->flush = 1;
++ efx->phy_powered = 1;
++ efx->loopback_mode = mode;
++ efx_reconfigure_port(efx, 0);
++
++ /* Wait for the PHY to signal the link is up */
++ count = 0;
++ do {
++ struct efx_channel *channel = &efx->channel[0];
++
++ (void) efx->mac_op->check_hw(efx);
++ schedule_timeout_uninterruptible(HZ / 10);
++ if (channel->work_pending)
++ efx_process_channel_now(channel);
++ /* Wait for PHY events to be processed */
++ flush_workqueue(efx->workqueue);
++ rmb();
++ } while ((++count < 20) && !efx->link_up);
++
++ /* The link should now be up. If it isn't, there is no point
++ * in attempting a loopback test */
++ if (!efx->link_up) {
++ EFX_ERR(efx, "loopback %s never came up\n",
++ LOOPBACK_MODE(efx));
++ rc = -EIO;
++ goto out;
++ }
++
++ EFX_LOG(efx, "link came up in %s loopback in %d iterations\n",
++ LOOPBACK_MODE(efx), count);
++
++ /* Test every TX queue */
++ efx_for_each_tx_queue(tx_queue, efx) {
++ rc |= efx_test_loopback_safely(efx, tx_queue,
++ &tests->loopback[mode]);
++ if (rc)
++ goto fail;
++ }
++
++ continue;
++
++fail:
++ if (retry) {
++ /* Give the PHY a kick by pretending to move into
++ * a Falcon internal loopback mode, then back out */
++ int first = ffs(efx->loopback_modes) - 1;
++
++ EFX_INFO(efx, "retrying %s loopback\n",
++ LOOPBACK_MODE(efx));
++
++ state->flush = 1;
++ efx->loopback_mode = first;
++ efx_reconfigure_port(efx, 0);
++
++ retry = rc = 0;
++ --mode;
++ continue;
++ }
++ break;
++ }
++
++ out:
++ /* Take out of loopback and restore PHY settings */
++ state->flush = 1;
++ efx->loopback_mode = old_mode;
++ efx->phy_powered = old_powered;
++ /* Push the loopback change, and restore any other
++ * settings we may have trodden on */
++ (void) efx_ethtool_set_settings(efx->net_dev, &ecmd);
++
++ return rc;
++}
++
++/**************************************************************************
++ *
++ * Entry points
++ *
++ *************************************************************************/
++
++/* Online (i.e. non-disruptive) testing
++ *
++ * This checks interrupt generation, event delivery and PHY presence.
++ * The caller should hold the suspend lock
++ *
++ */
++int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests)
++{
++ struct efx_channel *channel;
++ int rc = 0;
++
++ ASSERT_RTNL();
++
++ EFX_LOG(efx, "performing online self-tests\n");
++
++ rc |= efx_test_interrupts(efx, tests);
++ efx_for_each_channel(channel, efx) {
++ if (channel->has_interrupt)
++ rc |= efx_test_eventq_irq(channel, tests);
++ else
++ rc |= efx_test_eventq(channel, tests);
++ }
++ rc |= efx_test_phy(efx, tests);
++
++ if (rc)
++ EFX_ERR(efx, "failed online self-tests\n");
++
++ return rc;
++}
++
++/* Offline (i.e. disruptive) testing
++ * This checks MAC and PHY loopback on the specified port. The caller
++ * should hold the rtnl lock
++ */
++int efx_offline_test(struct efx_nic *efx,
++ struct efx_self_tests *tests, unsigned int loopback_modes)
++{
++ struct efx_selftest_state *state;
++ int rc = 0;
++
++ ASSERT_RTNL();
++
++ EFX_LOG(efx, "performing offline self-tests\n");
++
++ /* Create a selftest_state structure to hold state for the test */
++ state = kzalloc(sizeof(*state), GFP_KERNEL);
++ if (state == NULL) {
++ rc = -ENOMEM;
++ goto out;
++ }
++
++ /* Set the port loopback_selftest member. From this point on
++ * all received packets will be dropped. Mark the state as
++ * "flushing" so all inflight packets are dropped */
++ BUG_ON(efx->loopback_selftest);
++ state->flush = 1;
++ efx->loopback_selftest = (void *)state;
++ wmb();
++
++ /* Test all loopback modes */
++ rc = efx_test_loopbacks(efx, tests, loopback_modes);
++
++ /* Tidy up the port test state */
++ efx->loopback_selftest = NULL;
++ wmb();
++ kfree(state);
++
++ out:
++ if (rc)
++ EFX_ERR(efx, "failed offline self-tests\n");
++
++ return rc;
++}
++
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/selftest.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/selftest.h
+--- linux-2.6.18.8/drivers/net/sfc/selftest.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/selftest.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,67 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_SELFTEST_H
++#define EFX_SELFTEST_H
++
++#include "net_driver.h"
++
++/*
++ * Self tests
++ */
++
++struct efx_loopback_self_tests {
++ int tx_sent[EFX_MAX_TX_QUEUES];
++ int tx_done[EFX_MAX_TX_QUEUES];
++ int rx_good;
++ int rx_bad;
++};
++
++/* Efx self test results
++ * For fields which are not counters, 1 indicates success and -1
++ * indicates failure.
++ */
++struct efx_self_tests {
++ int interrupt;
++ int eventq_dma[EFX_MAX_CHANNELS];
++ int eventq_int[EFX_MAX_CHANNELS];
++ int eventq_poll[EFX_MAX_CHANNELS];
++ int phy_ok;
++ int loopback_speed;
++ int loopback_full_duplex;
++ struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX];
++};
++
++extern void efx_loopback_rx_packet(struct efx_nic *efx,
++ const char *buf_ptr, int pkt_len);
++extern int efx_online_test(struct efx_nic *efx,
++ struct efx_self_tests *tests);
++extern int efx_offline_test(struct efx_nic *efx,
++ struct efx_self_tests *tests,
++ unsigned int loopback_modes);
++
++#endif /* EFX_SELFTEST_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/assert_valid.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/assert_valid.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/assert_valid.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/assert_valid.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,95 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains functions to assert validness of resources and
++ * resource manager in DEBUG build of the resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/sysdep.h>
++
++#ifndef NDEBUG
++#include <ci/efrm/resource.h>
++#include <ci/efrm/driver_private.h>
++#include <ci/efrm/debug.h>
++
++void
++efrm_resource_manager_assert_valid(struct efrm_resource_manager *rm,
++ const char *file, int line)
++{
++ _EFRM_ASSERT(rm, file, line);
++ _EFRM_ASSERT(rm->rm_name, file, line);
++ _EFRM_ASSERT(rm->rm_type < EFRM_RESOURCE_NUM, file, line);
++ _EFRM_ASSERT(rm->rm_table, file, line);
++ _EFRM_ASSERT(rm->rm_table_size > 0, file, line);
++ _EFRM_ASSERT(rm->rm_dtor, file, line);
++}
++EXPORT_SYMBOL(efrm_resource_manager_assert_valid);
++
++/*
++ * \param rs resource to validate
++ * \param ref_count_is_zero One of 3 values
++ * > 0 - check ref count is zero
++ * = 0 - check ref count is non-zero
++ * < 0 - ref count could be any value
++ */
++void
++efrm_resource_assert_valid(struct efrm_resource *rs, int ref_count_is_zero,
++ const char *file, int line)
++{
++ struct efrm_resource_manager *rm;
++
++ _EFRM_ASSERT(rs, file, line);
++
++ if (ref_count_is_zero >= 0) {
++ if (!(ref_count_is_zero || atomic_read(&rs->rs_ref_count) > 0)
++ || !(!ref_count_is_zero
++ || atomic_read(&rs->rs_ref_count) == 0))
++ EFRM_WARN("%s: check %szero ref=%d " EFRM_RESOURCE_FMT,
++ __FUNCTION__,
++ ref_count_is_zero == 0 ? "non-" : "",
++ atomic_read(&rs->rs_ref_count),
++ EFRM_RESOURCE_PRI_ARG(rs->rs_handle));
++
++ _EFRM_ASSERT(!(ref_count_is_zero == 0) ||
++ atomic_read(&rs->rs_ref_count) != 0, file, line);
++ _EFRM_ASSERT(!(ref_count_is_zero > 0) ||
++ atomic_read(&rs->rs_ref_count) == 0, file, line);
++ }
++
++ rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
++ efrm_resource_manager_assert_valid(rm, file, line);
++}
++EXPORT_SYMBOL(efrm_resource_assert_valid);
++
++#endif
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/buddy.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/buddy.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/buddy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/buddy.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,307 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains implementation of a buddy allocator.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efhw/common.h> /* get uintXX types on win32 */
++#include <ci/efrm/sysdep.h>
++#include <ci/efrm/buddy.h>
++#include <ci/efrm/debug.h>
++
++#if 1
++#define DEBUG_ALLOC(x)
++#else
++#define DEBUG_ALLOC(x) x
++
++static inline void efrm_buddy_dump(struct efrm_buddy_allocator *b)
++{
++ unsigned o;
++
++ EFRM_NOTICE("%s: dump allocator with order %u",
++ __FUNCTION__, b->order);
++ for (o = 0; o <= b->order; o++) {
++ struct list_head *l = &b->free_lists[o];
++ while (l->next != &b->free_lists[o]) {
++ l = l->next;
++ EFRM_NOTICE("%s: order %x: %zx", __FUNCTION__, o,
++ l - b->links);
++ }
++ }
++}
++#endif
++
++/*
++ * The purpose of the following inline functions is to give the
++ * understandable names to the simple actions.
++ */
++static inline void
++efrm_buddy_free_list_add(struct efrm_buddy_allocator *b,
++ unsigned order, unsigned addr)
++{
++ list_add(&b->links[addr], &b->free_lists[order]);
++ b->orders[addr] = (uint8_t) b->order;
++}
++static inline void
++efrm_buddy_free_list_del(struct efrm_buddy_allocator *b, unsigned addr)
++{
++ list_del(&b->links[addr]);
++ b->links[addr].next = NULL;
++}
++static inline int
++efrm_buddy_free_list_empty(struct efrm_buddy_allocator *b, unsigned order)
++{
++ return list_empty(&b->free_lists[order]);
++}
++static inline unsigned
++efrm_buddy_free_list_pop(struct efrm_buddy_allocator *b, unsigned order)
++{
++ struct list_head *l = list_pop(&b->free_lists[order]);
++ l->next = NULL;
++ return (unsigned)(l - b->links);
++}
++static inline int
++efrm_buddy_addr_in_free_list(struct efrm_buddy_allocator *b, unsigned addr)
++{
++ return b->links[addr].next != NULL;
++}
++static inline unsigned
++efrm_buddy_free_list_first(struct efrm_buddy_allocator *b, unsigned order)
++{
++ return (unsigned)(b->free_lists[order].next - b->links);
++}
++
++int efrm_buddy_ctor(struct efrm_buddy_allocator *b, unsigned order)
++{
++ unsigned o;
++ unsigned size = 1 << order;
++
++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __FUNCTION__, order));
++ EFRM_ASSERT(b);
++ EFRM_ASSERT(order <= sizeof(unsigned) * 8 - 1);
++
++ b->order = order;
++ b->free_lists = vmalloc((order + 1) * sizeof(struct list_head));
++ if (b->free_lists == NULL)
++ goto fail1;
++
++ b->links = vmalloc(size * sizeof(struct list_head));
++ if (b->links == NULL)
++ goto fail2;
++
++ b->orders = vmalloc(size);
++ if (b->orders == NULL)
++ goto fail3;
++
++ memset(b->links, 0, size * sizeof(struct list_head));
++
++ for (o = 0; o <= b->order; ++o)
++ INIT_LIST_HEAD(b->free_lists + o);
++
++ efrm_buddy_free_list_add(b, b->order, 0);
++
++ return 0;
++
++fail3:
++ vfree(b->links);
++fail2:
++ vfree(b->free_lists);
++fail1:
++ return -ENOMEM;
++}
++
++void efrm_buddy_dtor(struct efrm_buddy_allocator *b)
++{
++ EFRM_ASSERT(b);
++
++ vfree(b->free_lists);
++ vfree(b->links);
++ vfree(b->orders);
++}
++
++int efrm_buddy_alloc(struct efrm_buddy_allocator *b, unsigned order)
++{
++ unsigned smallest;
++ unsigned addr;
++
++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __FUNCTION__, order));
++ EFRM_ASSERT(b);
++
++ /* Find smallest chunk that is big enough. ?? Can optimise this by
++ ** keeping array of pointers to smallest chunk for each order.
++ */
++ smallest = order;
++ while (smallest <= b->order &&
++ efrm_buddy_free_list_empty(b, smallest))
++ ++smallest;
++
++ if (smallest > b->order) {
++ DEBUG_ALLOC(EFRM_NOTICE
++ ("buddy - alloc order %d failed - max order %d",
++ order, b->order););
++ return -ENOMEM;
++ }
++
++ /* Split blocks until we get one of the correct size. */
++ addr = efrm_buddy_free_list_pop(b, smallest);
++
++ DEBUG_ALLOC(EFRM_NOTICE("buddy - alloc %x order %d cut from order %d",
++ addr, order, smallest););
++ while (smallest-- > order)
++ efrm_buddy_free_list_add(b, smallest, addr + (1 << smallest));
++
++ EFRM_DO_DEBUG(b->orders[addr] = (uint8_t) order);
++
++ EFRM_ASSERT(addr < 1u << b->order);
++ return addr;
++}
++
++void
++efrm_buddy_free(struct efrm_buddy_allocator *b, unsigned addr,
++ unsigned order)
++{
++ unsigned buddy_addr;
++
++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u, %u)", __FUNCTION__, addr, order));
++ EFRM_ASSERT(b);
++ EFRM_ASSERT(order <= b->order);
++ EFRM_ASSERT((unsigned long)addr + ((unsigned long)1 << order) <=
++ (unsigned long)1 << b->order);
++ EFRM_ASSERT(!efrm_buddy_addr_in_free_list(b, addr));
++ EFRM_ASSERT(b->orders[addr] == order);
++
++ /* merge free blocks */
++ while (order < b->order) {
++ buddy_addr = addr ^ (1 << order);
++ if (!efrm_buddy_addr_in_free_list(b, buddy_addr) ||
++ b->orders[buddy_addr] != order)
++ break;
++ efrm_buddy_free_list_del(b, addr);
++ if (buddy_addr < addr)
++ addr = buddy_addr;
++ ++order;
++ }
++
++ DEBUG_ALLOC(EFRM_NOTICE
++ ("buddy - free %x merged into order %d", addr, order););
++ efrm_buddy_free_list_add(b, order, addr);
++}
++
++void efrm_buddy_reserve_at_start(struct efrm_buddy_allocator *b, unsigned n)
++{
++ int addr;
++ unsigned o;
++ EFRM_DO_DEBUG(int n_save = n);
++
++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __FUNCTION__, n));
++ EFRM_ASSERT(b);
++ EFRM_ASSERT(n <= 1u << b->order && n > 0);
++ /* Whole space must be free. */
++ EFRM_ASSERT(!efrm_buddy_free_list_empty(b, b->order));
++
++ o = fls(n);
++
++ while (n) {
++ while (((unsigned)1 << o) > n)
++ --o;
++ EFRM_ASSERT(((unsigned)1 << o) <= n);
++ addr = efrm_buddy_alloc(b, o);
++ EFRM_ASSERT(addr + (1 << o) <= n_save);
++ n -= 1 << o;
++ }
++}
++
++static int
++__efrm_buddy_reserve_at_end(struct efrm_buddy_allocator *b, unsigned order,
++ int threshold)
++{
++ unsigned o, addr;
++
++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u, %d)", __FUNCTION__, order, threshold));
++ EFRM_ASSERT(b);
++
++ /* Find largest block; there must be one big enough (or caller has
++ ** goofed).
++ */
++ for (o = b->order;; --o) {
++ if (efrm_buddy_free_list_empty(b, o))
++ continue;
++ addr = efrm_buddy_free_list_first(b, o);
++ if (addr + (1 << o) <= (unsigned)threshold)
++ continue;
++ break;
++ }
++ EFRM_ASSERT(o >= order);
++
++ /* Split down (keeping second half) until we reach
++ * the requested size. */
++ addr = efrm_buddy_free_list_pop(b, o);
++
++ while (o-- > order) {
++ efrm_buddy_free_list_add(b, o, addr);
++ addr += 1 << o;
++ }
++
++ EFRM_DO_DEBUG(b->orders[addr] = (uint8_t) order);
++
++ return addr;
++}
++
++void efrm_buddy_reserve_at_end(struct efrm_buddy_allocator *b, unsigned n)
++{
++ int addr, threshold;
++ unsigned o;
++ EFRM_DO_DEBUG(int n_save = n);
++
++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __FUNCTION__, n));
++ DEBUG_ALLOC(efrm_buddy_dump(b));
++ EFRM_ASSERT(b);
++ EFRM_ASSERT(n <= 1u << b->order);
++
++ if (!n)
++ return;
++
++ threshold = (1 << b->order) - n;
++ o = fls(n);
++
++ while (n) {
++ while (((unsigned)1 << o) > n)
++ --o;
++ EFRM_ASSERT(((unsigned)1 << o) <= n);
++ addr = __efrm_buddy_reserve_at_end(b, o, threshold);
++ EFRM_ASSERT(addr >= (1 << b->order) - n_save);
++ n -= 1 << o;
++ }
++ DEBUG_ALLOC(efrm_buddy_dump(b));
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/buffer_table.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/buffer_table.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/buffer_table.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/buffer_table.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,210 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains abstraction of the buffer table on the NIC.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++** Might be worth keeping a bitmap of which entries are clear. Then we
++** wouldn't need to clear them all again when we free an allocation.
++*/
++
++#include <ci/efrm/debug.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efrm/nic_table.h>
++#include <ci/efrm/buffer_table.h>
++#include <ci/efrm/buddy.h>
++
++/*! Comment? */
++struct efrm_buffer_table {
++ spinlock_t lock;
++ struct efrm_buddy_allocator buddy;
++};
++
++/* Efab buffer state. */
++static struct efrm_buffer_table efrm_buffers;
++
++int efrm_buffer_table_ctor(unsigned low, unsigned high)
++{
++ int log2_n_entries, rc;
++
++ EFRM_ASSERT(high > 0);
++ EFRM_ASSERT(low < high);
++
++ EFRM_TRACE("efrm_buffer_table_ctor: low=%u high=%u", low, high);
++ EFRM_NOTICE("efrm_buffer_table_ctor: low=%u high=%u", low, high);
++
++ log2_n_entries = fls(high - 1);
++
++ rc = efrm_buddy_ctor(&efrm_buffers.buddy, log2_n_entries);
++ if (rc < 0) {
++ EFRM_ERR("efrm_buffer_table_ctor: efrm_buddy_ctor(%d) "
++ "failed (%d)", log2_n_entries, rc);
++ return rc;
++ }
++
++ spin_lock_init(&efrm_buffers.lock);
++
++ efrm_buddy_reserve_at_start(&efrm_buffers.buddy, low);
++ efrm_buddy_reserve_at_end(&efrm_buffers.buddy,
++ (1 << log2_n_entries) - high);
++
++ EFRM_TRACE("efrm_buffer_table_ctor: done");
++
++ return 0;
++}
++
++void efrm_buffer_table_dtor(void)
++{
++ /* ?? debug check that all allocations have been freed? */
++
++ spin_lock_destroy(&efrm_buffers.lock);
++ efrm_buddy_dtor(&efrm_buffers.buddy);
++
++ EFRM_TRACE("efrm_buffer_table_dtor: done");
++}
++
++/**********************************************************************/
++
++int
++efrm_buffer_table_alloc(unsigned order,
++ struct efhw_buffer_table_allocation *a)
++{
++ irq_flags_t lock_flags;
++ int rc;
++
++ EFRM_ASSERT(&efrm_buffers.buddy);
++ EFRM_ASSERT(a);
++
++ /* Round up to multiple of two, as the buffer clear logic works in
++ * pairs when not in "full" mode. */
++ order = max_t(unsigned, order, 1);
++
++ spin_lock_irqsave(&efrm_buffers.lock, lock_flags);
++ rc = efrm_buddy_alloc(&efrm_buffers.buddy, order);
++ spin_unlock_irqrestore(&efrm_buffers.lock, lock_flags);
++
++ if (rc < 0) {
++ EFRM_ERR("efrm_buffer_table_alloc: failed (n=%ld) rc %d",
++ 1ul << order, rc);
++ return rc;
++ }
++
++ EFRM_TRACE("efrm_buffer_table_alloc: base=%d n=%ld",
++ rc, 1ul << order);
++ a->order = order;
++ a->base = (unsigned)rc;
++ return 0;
++}
++
++void efrm_buffer_table_free(struct efhw_buffer_table_allocation *a)
++{
++ irq_flags_t lock_flags;
++ struct efhw_nic *nic;
++ int nic_i;
++
++ EFRM_ASSERT(&efrm_buffers.buddy);
++ EFRM_ASSERT(a);
++ EFRM_ASSERT(a->base != -1);
++ EFRM_ASSERT((unsigned long)a->base + (1ul << a->order) <=
++ efrm_buddy_size(&efrm_buffers.buddy));
++
++ EFRM_TRACE("efrm_buffer_table_free: base=%d n=%ld",
++ a->base, (1ul << a->order));
++
++ EFRM_FOR_EACH_NIC(nic_i, nic)
++ efhw_nic_buffer_table_clear(nic, a->base, 1ul << a->order);
++
++ spin_lock_irqsave(&efrm_buffers.lock, lock_flags);
++ efrm_buddy_free(&efrm_buffers.buddy, a->base, a->order);
++ spin_unlock_irqrestore(&efrm_buffers.lock, lock_flags);
++
++ EFRM_DO_DEBUG(a->base = a->order = -1);
++}
++
++/**********************************************************************/
++
++void
++efrm_buffer_table_set(struct efhw_buffer_table_allocation *a,
++ unsigned i, dma_addr_t dma_addr, int owner)
++{
++ struct efhw_nic *nic;
++ int nic_i;
++
++ EFRM_ASSERT(a);
++ EFRM_ASSERT(i < (unsigned)1 << a->order);
++ EFRM_FOR_EACH_NIC(nic_i, nic)
++ efhw_nic_buffer_table_set(nic, dma_addr, EFHW_NIC_PAGE_SIZE,
++ 0, owner, a->base + i);
++ /* NB. No commit Caller should call efrm_buffer_table_commit. There
++ are underlying hardware constraints regarding the number of
++ buffer table entries which can be pushed before commiting. */
++}
++
++unsigned long efrm_buffer_table_size(void)
++{
++ return efrm_buddy_size(&efrm_buffers.buddy);
++}
++
++/**********************************************************************/
++
++int
++efrm_page_register(dma_addr_t dma_addr, int owner,
++ efhw_buffer_addr_t *buf_addr_out)
++{
++ struct efhw_buffer_table_allocation alloc;
++ int rc;
++
++ rc = efrm_buffer_table_alloc(0, &alloc);
++ if (rc == 0) {
++ efrm_buffer_table_set(&alloc, 0, dma_addr, owner);
++ efrm_buffer_table_commit();
++ *buf_addr_out = EFHW_BUFFER_ADDR(alloc.base, 0);
++ }
++ return rc;
++}
++EXPORT_SYMBOL(efrm_page_register);
++
++void efrm_page_unregister(efhw_buffer_addr_t buf_addr)
++{
++ struct efhw_buffer_table_allocation alloc;
++
++ alloc.order = 0;
++ alloc.base = EFHW_BUFFER_PAGE(buf_addr);
++ efrm_buffer_table_free(&alloc);
++}
++EXPORT_SYMBOL(efrm_page_unregister);
++
++void efrm_buffer_table_commit(void)
++{
++ struct efhw_nic *nic;
++ int nic_i;
++
++ EFRM_FOR_EACH_NIC(nic_i, nic)
++ efhw_nic_buffer_table_commit(nic);
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,68 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC hardware interface common
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_HARDWARE_COMMON_H__
++#define __CI_DRIVER_EFAB_HARDWARE_COMMON_H__
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric constants
++ *
++ *---------------------------------------------------------------------------*/
++
++#define EFHW_1K 0x00000400u
++#define EFHW_2K 0x00000800u
++#define EFHW_4K 0x00001000u
++#define EFHW_8K 0x00002000u
++#define EFHW_16K 0x00004000u
++#define EFHW_32K 0x00008000u
++#define EFHW_64K 0x00010000u
++#define EFHW_128K 0x00020000u
++#define EFHW_256K 0x00040000u
++#define EFHW_512K 0x00080000u
++#define EFHW_1M 0x00100000u
++#define EFHW_2M 0x00200000u
++#define EFHW_4M 0x00400000u
++#define EFHW_8M 0x00800000u
++#define EFHW_16M 0x01000000u
++#define EFHW_32M 0x02000000u
++#define EFHW_48M 0x03000000u
++#define EFHW_64M 0x04000000u
++#define EFHW_128M 0x08000000u
++#define EFHW_256M 0x10000000u
++#define EFHW_512M 0x20000000u
++#define EFHW_1G 0x40000000u
++#define EFHW_2G 0x80000000u
++#define EFHW_4G 0x100000000ULL
++#define EFHW_8G 0x200000000ULL
++
++#endif /* __CI_DRIVER_EFAB_HARDWARE_COMMON_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1149 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) core register
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#define FALCON_EXTENDED_P_BAR 1
++
++/*************---- Bus Interface Unit Registers C Header ----*************/
++#define IOM_IND_ADR_REG_OFST 0x0 /* IO-mapped indirect access address
++ register */
++ #define IOM_AUTO_ADR_INC_EN_LBN 16
++ #define IOM_AUTO_ADR_INC_EN_WIDTH 1
++ #define IOM_IND_ADR_LBN 0
++ #define IOM_IND_ADR_WIDTH 16
++#define IOM_IND_DAT_REG_OFST 0x4 /* IO-mapped indirect access data register */
++ #define IOM_IND_DAT_LBN 0
++ #define IOM_IND_DAT_WIDTH 32
++#define ADR_REGION_REG_KER_OFST 0x0 /* Address region register */
++#define ADR_REGION_REG_OFST 0x0 /* Address region register */
++ #define ADR_REGION3_LBN 96
++ #define ADR_REGION3_WIDTH 18
++ #define ADR_REGION2_LBN 64
++ #define ADR_REGION2_WIDTH 18
++ #define ADR_REGION1_LBN 32
++ #define ADR_REGION1_WIDTH 18
++ #define ADR_REGION0_LBN 0
++ #define ADR_REGION0_WIDTH 18
++#define INT_EN_REG_KER_OFST 0x10 /* Kernel driver Interrupt enable register */
++ #define KER_INT_CHAR_LBN 4
++ #define KER_INT_CHAR_WIDTH 1
++ #define KER_INT_KER_LBN 3
++ #define KER_INT_KER_WIDTH 1
++ #define ILL_ADR_ERR_INT_EN_KER_LBN 2
++ #define ILL_ADR_ERR_INT_EN_KER_WIDTH 1
++ #define SRM_PERR_INT_EN_KER_LBN 1
++ #define SRM_PERR_INT_EN_KER_WIDTH 1
++ #define DRV_INT_EN_KER_LBN 0
++ #define DRV_INT_EN_KER_WIDTH 1
++#define INT_EN_REG_CHAR_OFST 0x20 /* Char Driver interrupt enable register */
++ #define CHAR_INT_CHAR_LBN 4
++ #define CHAR_INT_CHAR_WIDTH 1
++ #define CHAR_INT_KER_LBN 3
++ #define CHAR_INT_KER_WIDTH 1
++ #define ILL_ADR_ERR_INT_EN_CHAR_LBN 2
++ #define ILL_ADR_ERR_INT_EN_CHAR_WIDTH 1
++ #define SRM_PERR_INT_EN_CHAR_LBN 1
++ #define SRM_PERR_INT_EN_CHAR_WIDTH 1
++ #define DRV_INT_EN_CHAR_LBN 0
++ #define DRV_INT_EN_CHAR_WIDTH 1
++#define INT_ADR_REG_KER_OFST 0x30 /* Interrupt host address for Kernel driver */
++ #define INT_ADR_KER_LBN 0
++ #define INT_ADR_KER_WIDTH 64
++ #define DRV_INT_KER_LBN 32
++ #define DRV_INT_KER_WIDTH 1
++ #define EV_FF_HALF_INT_KER_LBN 3
++ #define EV_FF_HALF_INT_KER_WIDTH 1
++ #define EV_FF_FULL_INT_KER_LBN 2
++ #define EV_FF_FULL_INT_KER_WIDTH 1
++ #define ILL_ADR_ERR_INT_KER_LBN 1
++ #define ILL_ADR_ERR_INT_KER_WIDTH 1
++ #define SRAM_PERR_INT_KER_LBN 0
++ #define SRAM_PERR_INT_KER_WIDTH 1
++#define INT_ADR_REG_CHAR_OFST 0x40 /* Interrupt host address for Char driver */
++ #define INT_ADR_CHAR_LBN 0
++ #define INT_ADR_CHAR_WIDTH 64
++ #define DRV_INT_CHAR_LBN 32
++ #define DRV_INT_CHAR_WIDTH 1
++ #define EV_FF_HALF_INT_CHAR_LBN 3
++ #define EV_FF_HALF_INT_CHAR_WIDTH 1
++ #define EV_FF_FULL_INT_CHAR_LBN 2
++ #define EV_FF_FULL_INT_CHAR_WIDTH 1
++ #define ILL_ADR_ERR_INT_CHAR_LBN 1
++ #define ILL_ADR_ERR_INT_CHAR_WIDTH 1
++ #define SRAM_PERR_INT_CHAR_LBN 0
++ #define SRAM_PERR_INT_CHAR_WIDTH 1
++#define INT_ISR0_B0_OFST 0x90 /* B0 only */
++#define INT_ISR1_B0_OFST 0xA0
++#define INT_ACK_REG_KER_A1_OFST 0x50 /* Kernel interrupt acknowledge register */
++ #define RESERVED_LBN 0
++ #define RESERVED_WIDTH 32
++#define INT_ACK_REG_CHAR_A1_OFST 0x60 /* CHAR interrupt acknowledge register */
++ #define RESERVED_LBN 0
++ #define RESERVED_WIDTH 32
++/*************---- Global CSR Registers C Header ----*************/
++#define STRAP_REG_KER_OFST 0x200 /* ASIC strap status register */
++#define STRAP_REG_OFST 0x200 /* ASIC strap status register */
++ #define ONCHIP_SRAM_LBN 16
++ #define ONCHIP_SRAM_WIDTH 0
++ #define STRAP_ISCSI_EN_LBN 3
++ #define STRAP_ISCSI_EN_WIDTH 1
++ #define STRAP_PINS_LBN 0
++ #define STRAP_PINS_WIDTH 3
++#define GPIO_CTL_REG_KER_OFST 0x210 /* GPIO control register */
++#define GPIO_CTL_REG_OFST 0x210 /* GPIO control register */
++ #define GPIO_OEN_LBN 24
++ #define GPIO_OEN_WIDTH 4
++ #define GPIO_OUT_LBN 16
++ #define GPIO_OUT_WIDTH 4
++ #define GPIO_IN_LBN 8
++ #define GPIO_IN_WIDTH 4
++ #define GPIO_PWRUP_VALUE_LBN 0
++ #define GPIO_PWRUP_VALUE_WIDTH 4
++#define GLB_CTL_REG_KER_OFST 0x220 /* Global control register */
++#define GLB_CTL_REG_OFST 0x220 /* Global control register */
++ #define SWRST_LBN 0
++ #define SWRST_WIDTH 1
++#define FATAL_INTR_REG_KER_OFST 0x230 /* Fatal interrupt register for Kernel */
++ #define PCI_BUSERR_INT_KER_EN_LBN 43
++ #define PCI_BUSERR_INT_KER_EN_WIDTH 1
++ #define SRAM_OOB_INT_KER_EN_LBN 42
++ #define SRAM_OOB_INT_KER_EN_WIDTH 1
++ #define BUFID_OOB_INT_KER_EN_LBN 41
++ #define BUFID_OOB_INT_KER_EN_WIDTH 1
++ #define MEM_PERR_INT_KER_EN_LBN 40
++ #define MEM_PERR_INT_KER_EN_WIDTH 1
++ #define RBUF_OWN_INT_KER_EN_LBN 39
++ #define RBUF_OWN_INT_KER_EN_WIDTH 1
++ #define TBUF_OWN_INT_KER_EN_LBN 38
++ #define TBUF_OWN_INT_KER_EN_WIDTH 1
++ #define RDESCQ_OWN_INT_KER_EN_LBN 37
++ #define RDESCQ_OWN_INT_KER_EN_WIDTH 1
++ #define TDESCQ_OWN_INT_KER_EN_LBN 36
++ #define TDESCQ_OWN_INT_KER_EN_WIDTH 1
++ #define EVQ_OWN_INT_KER_EN_LBN 35
++ #define EVQ_OWN_INT_KER_EN_WIDTH 1
++ #define EVFF_OFLO_INT_KER_EN_LBN 34
++ #define EVFF_OFLO_INT_KER_EN_WIDTH 1
++ #define ILL_ADR_INT_KER_EN_LBN 33
++ #define ILL_ADR_INT_KER_EN_WIDTH 1
++ #define SRM_PERR_INT_KER_EN_LBN 32
++ #define SRM_PERR_INT_KER_EN_WIDTH 1
++ #define PCI_BUSERR_INT_KER_LBN 11
++ #define PCI_BUSERR_INT_KER_WIDTH 1
++ #define SRAM_OOB_INT_KER_LBN 10
++ #define SRAM_OOB_INT_KER_WIDTH 1
++ #define BUFID_OOB_INT_KER_LBN 9
++ #define BUFID_OOB_INT_KER_WIDTH 1
++ #define MEM_PERR_INT_KER_LBN 8
++ #define MEM_PERR_INT_KER_WIDTH 1
++ #define RBUF_OWN_INT_KER_LBN 7
++ #define RBUF_OWN_INT_KER_WIDTH 1
++ #define TBUF_OWN_INT_KER_LBN 6
++ #define TBUF_OWN_INT_KER_WIDTH 1
++ #define RDESCQ_OWN_INT_KER_LBN 5
++ #define RDESCQ_OWN_INT_KER_WIDTH 1
++ #define TDESCQ_OWN_INT_KER_LBN 4
++ #define TDESCQ_OWN_INT_KER_WIDTH 1
++ #define EVQ_OWN_INT_KER_LBN 3
++ #define EVQ_OWN_INT_KER_WIDTH 1
++ #define EVFF_OFLO_INT_KER_LBN 2
++ #define EVFF_OFLO_INT_KER_WIDTH 1
++ #define ILL_ADR_INT_KER_LBN 1
++ #define ILL_ADR_INT_KER_WIDTH 1
++ #define SRM_PERR_INT_KER_LBN 0
++ #define SRM_PERR_INT_KER_WIDTH 1
++#define FATAL_INTR_REG_OFST 0x240 /* Fatal interrupt register for Char */
++ #define PCI_BUSERR_INT_CHAR_EN_LBN 43
++ #define PCI_BUSERR_INT_CHAR_EN_WIDTH 1
++ #define SRAM_OOB_INT_CHAR_EN_LBN 42
++ #define SRAM_OOB_INT_CHAR_EN_WIDTH 1
++ #define BUFID_OOB_INT_CHAR_EN_LBN 41
++ #define BUFID_OOB_INT_CHAR_EN_WIDTH 1
++ #define MEM_PERR_INT_CHAR_EN_LBN 40
++ #define MEM_PERR_INT_CHAR_EN_WIDTH 1
++ #define RBUF_OWN_INT_CHAR_EN_LBN 39
++ #define RBUF_OWN_INT_CHAR_EN_WIDTH 1
++ #define TBUF_OWN_INT_CHAR_EN_LBN 38
++ #define TBUF_OWN_INT_CHAR_EN_WIDTH 1
++ #define RDESCQ_OWN_INT_CHAR_EN_LBN 37
++ #define RDESCQ_OWN_INT_CHAR_EN_WIDTH 1
++ #define TDESCQ_OWN_INT_CHAR_EN_LBN 36
++ #define TDESCQ_OWN_INT_CHAR_EN_WIDTH 1
++ #define EVQ_OWN_INT_CHAR_EN_LBN 35
++ #define EVQ_OWN_INT_CHAR_EN_WIDTH 1
++ #define EVFF_OFLO_INT_CHAR_EN_LBN 34
++ #define EVFF_OFLO_INT_CHAR_EN_WIDTH 1
++ #define ILL_ADR_INT_CHAR_EN_LBN 33
++ #define ILL_ADR_INT_CHAR_EN_WIDTH 1
++ #define SRM_PERR_INT_CHAR_EN_LBN 32
++ #define SRM_PERR_INT_CHAR_EN_WIDTH 1
++ #define FATAL_INTR_REG_EN_BITS 0xffffffffffffffffULL
++ #define PCI_BUSERR_INT_CHAR_LBN 11
++ #define PCI_BUSERR_INT_CHAR_WIDTH 1
++ #define SRAM_OOB_INT_CHAR_LBN 10
++ #define SRAM_OOB_INT_CHAR_WIDTH 1
++ #define BUFID_OOB_INT_CHAR_LBN 9
++ #define BUFID_OOB_INT_CHAR_WIDTH 1
++ #define MEM_PERR_INT_CHAR_LBN 8
++ #define MEM_PERR_INT_CHAR_WIDTH 1
++ #define RBUF_OWN_INT_CHAR_LBN 7
++ #define RBUF_OWN_INT_CHAR_WIDTH 1
++ #define TBUF_OWN_INT_CHAR_LBN 6
++ #define TBUF_OWN_INT_CHAR_WIDTH 1
++ #define RDESCQ_OWN_INT_CHAR_LBN 5
++ #define RDESCQ_OWN_INT_CHAR_WIDTH 1
++ #define TDESCQ_OWN_INT_CHAR_LBN 4
++ #define TDESCQ_OWN_INT_CHAR_WIDTH 1
++ #define EVQ_OWN_INT_CHAR_LBN 3
++ #define EVQ_OWN_INT_CHAR_WIDTH 1
++ #define EVFF_OFLO_INT_CHAR_LBN 2
++ #define EVFF_OFLO_INT_CHAR_WIDTH 1
++ #define ILL_ADR_INT_CHAR_LBN 1
++ #define ILL_ADR_INT_CHAR_WIDTH 1
++ #define SRM_PERR_INT_CHAR_LBN 0
++ #define SRM_PERR_INT_CHAR_WIDTH 1
++#define DP_CTRL_REG_OFST 0x250 /* Datapath control register */
++ #define FLS_EVQ_ID_LBN 0
++ #define FLS_EVQ_ID_WIDTH 12
++#define MEM_STAT_REG_KER_OFST 0x260 /* Memory status register */
++#define MEM_STAT_REG_OFST 0x260 /* Memory status register */
++ #define MEM_PERR_VEC_LBN 53
++ #define MEM_PERR_VEC_WIDTH 38
++ #define MBIST_CORR_LBN 38
++ #define MBIST_CORR_WIDTH 15
++ #define MBIST_ERR_LBN 0
++ #define MBIST_ERR_WIDTH 38
++#define DEBUG_REG_KER_OFST 0x270 /* Debug register */
++#define DEBUG_REG_OFST 0x270 /* Debug register */
++ #define DEBUG_BLK_SEL2_LBN 47
++ #define DEBUG_BLK_SEL2_WIDTH 3
++ #define DEBUG_BLK_SEL1_LBN 44
++ #define DEBUG_BLK_SEL1_WIDTH 3
++ #define DEBUG_BLK_SEL0_LBN 41
++ #define DEBUG_BLK_SEL0_WIDTH 3
++ #define MISC_DEBUG_ADDR_LBN 36
++ #define MISC_DEBUG_ADDR_WIDTH 5
++ #define SERDES_DEBUG_ADDR_LBN 31
++ #define SERDES_DEBUG_ADDR_WIDTH 5
++ #define EM_DEBUG_ADDR_LBN 26
++ #define EM_DEBUG_ADDR_WIDTH 5
++ #define SR_DEBUG_ADDR_LBN 21
++ #define SR_DEBUG_ADDR_WIDTH 5
++ #define EV_DEBUG_ADDR_LBN 16
++ #define EV_DEBUG_ADDR_WIDTH 5
++ #define RX_DEBUG_ADDR_LBN 11
++ #define RX_DEBUG_ADDR_WIDTH 5
++ #define TX_DEBUG_ADDR_LBN 6
++ #define TX_DEBUG_ADDR_WIDTH 5
++ #define BIU_DEBUG_ADDR_LBN 1
++ #define BIU_DEBUG_ADDR_WIDTH 5
++ #define DEBUG_EN_LBN 0
++ #define DEBUG_EN_WIDTH 1
++#define DRIVER_REG0_KER_OFST 0x280 /* Driver scratch register 0 */
++#define DRIVER_REG0_OFST 0x280 /* Driver scratch register 0 */
++ #define DRIVER_DW0_LBN 0
++ #define DRIVER_DW0_WIDTH 32
++#define DRIVER_REG1_KER_OFST 0x290 /* Driver scratch register 1 */
++#define DRIVER_REG1_OFST 0x290 /* Driver scratch register 1 */
++ #define DRIVER_DW1_LBN 0
++ #define DRIVER_DW1_WIDTH 32
++#define DRIVER_REG2_KER_OFST 0x2A0 /* Driver scratch register 2 */
++#define DRIVER_REG2_OFST 0x2A0 /* Driver scratch register 2 */
++ #define DRIVER_DW2_LBN 0
++ #define DRIVER_DW2_WIDTH 32
++#define DRIVER_REG3_KER_OFST 0x2B0 /* Driver scratch register 3 */
++#define DRIVER_REG3_OFST 0x2B0 /* Driver scratch register 3 */
++ #define DRIVER_DW3_LBN 0
++ #define DRIVER_DW3_WIDTH 32
++#define DRIVER_REG4_KER_OFST 0x2C0 /* Driver scratch register 4 */
++#define DRIVER_REG4_OFST 0x2C0 /* Driver scratch register 4 */
++ #define DRIVER_DW4_LBN 0
++ #define DRIVER_DW4_WIDTH 32
++#define DRIVER_REG5_KER_OFST 0x2D0 /* Driver scratch register 5 */
++#define DRIVER_REG5_OFST 0x2D0 /* Driver scratch register 5 */
++ #define DRIVER_DW5_LBN 0
++ #define DRIVER_DW5_WIDTH 32
++#define DRIVER_REG6_KER_OFST 0x2E0 /* Driver scratch register 6 */
++#define DRIVER_REG6_OFST 0x2E0 /* Driver scratch register 6 */
++ #define DRIVER_DW6_LBN 0
++ #define DRIVER_DW6_WIDTH 32
++#define DRIVER_REG7_KER_OFST 0x2F0 /* Driver scratch register 7 */
++#define DRIVER_REG7_OFST 0x2F0 /* Driver scratch register 7 */
++ #define DRIVER_DW7_LBN 0
++ #define DRIVER_DW7_WIDTH 32
++#define ALTERA_BUILD_REG_OFST 0x300 /* Altera build register */
++#define ALTERA_BUILD_REG_OFST 0x300 /* Altera build register */
++ #define ALTERA_BUILD_VER_LBN 0
++ #define ALTERA_BUILD_VER_WIDTH 32
++
++/* so called CSR spare register
++ - contains separate parity enable bits for the various internal memory
++ blocks */
++#define MEM_PARITY_ERR_EN_REG_KER 0x310
++#define MEM_PARITY_ALL_BLOCKS_EN_LBN 64
++#define MEM_PARITY_ALL_BLOCKS_EN_WIDTH 38
++#define MEM_PARITY_TX_DATA_EN_LBN 72
++#define MEM_PARITY_TX_DATA_EN_WIDTH 2
++
++/*************---- Event & Timer Module Registers C Header ----*************/
++
++#if FALCON_EXTENDED_P_BAR
++#define EVQ_RPTR_REG_KER_OFST 0x11B00 /* Event queue read pointer register */
++#else
++#define EVQ_RPTR_REG_KER_OFST 0x1B00 /* Event queue read pointer register */
++#endif
++
++#define EVQ_RPTR_REG_OFST 0xFA0000 /* Event queue read pointer register
++ array. */
++ #define EVQ_RPTR_LBN 0
++ #define EVQ_RPTR_WIDTH 15
++
++#if FALCON_EXTENDED_P_BAR
++#define EVQ_PTR_TBL_KER_OFST 0x11A00 /* Event queue pointer table for kernel
++ access */
++#else
++#define EVQ_PTR_TBL_KER_OFST 0x1A00 /* Event queue pointer table for kernel
++ access */
++#endif
++
++#define EVQ_PTR_TBL_CHAR_OFST 0xF60000 /* Event queue pointer table for char
++ direct access */
++ #define EVQ_WKUP_OR_INT_EN_LBN 39
++ #define EVQ_WKUP_OR_INT_EN_WIDTH 1
++ #define EVQ_NXT_WPTR_LBN 24
++ #define EVQ_NXT_WPTR_WIDTH 15
++ #define EVQ_EN_LBN 23
++ #define EVQ_EN_WIDTH 1
++ #define EVQ_SIZE_LBN 20
++ #define EVQ_SIZE_WIDTH 3
++ #define EVQ_BUF_BASE_ID_LBN 0
++ #define EVQ_BUF_BASE_ID_WIDTH 20
++#define TIMER_CMD_REG_KER_OFST 0x420 /* Timer table for kernel access.
++ Page-mapped */
++#define TIMER_CMD_REG_PAGE4_OFST 0x8420 /* Timer table for user-level access.
++ Page-mapped. For lowest 1K queues.
++ */
++#define TIMER_CMD_REG_PAGE123K_OFST 0x1000420 /* Timer table for user-level
++ access. Page-mapped.
++ For upper 3K queues. */
++#define TIMER_TBL_OFST 0xF70000 /* Timer table for char driver direct access */
++ #define TIMER_MODE_LBN 12
++ #define TIMER_MODE_WIDTH 2
++ #define TIMER_VAL_LBN 0
++ #define TIMER_VAL_WIDTH 12
++ #define TIMER_MODE_INT_HLDOFF 2
++ #define EVQ_BUF_SIZE_LBN 0
++ #define EVQ_BUF_SIZE_WIDTH 1
++#define DRV_EV_REG_KER_OFST 0x440 /* Driver generated event register */
++#define DRV_EV_REG_OFST 0x440 /* Driver generated event register */
++ #define DRV_EV_QID_LBN 64
++ #define DRV_EV_QID_WIDTH 12
++ #define DRV_EV_DATA_LBN 0
++ #define DRV_EV_DATA_WIDTH 64
++#define EVQ_CTL_REG_KER_OFST 0x450 /* Event queue control register */
++#define EVQ_CTL_REG_OFST 0x450 /* Event queue control register */
++ #define RX_EVQ_WAKEUP_MASK_B0_LBN 15
++ #define RX_EVQ_WAKEUP_MASK_B0_WIDTH 6
++ #define EVQ_OWNERR_CTL_LBN 14
++ #define EVQ_OWNERR_CTL_WIDTH 1
++ #define EVQ_FIFO_AF_TH_LBN 8
++ #define EVQ_FIFO_AF_TH_WIDTH 6
++ #define EVQ_FIFO_NOTAF_TH_LBN 0
++ #define EVQ_FIFO_NOTAF_TH_WIDTH 6
++/*************---- SRAM Module Registers C Header ----*************/
++#define BUF_TBL_CFG_REG_KER_OFST 0x600 /* Buffer table configuration register */
++#define BUF_TBL_CFG_REG_OFST 0x600 /* Buffer table configuration register */
++ #define BUF_TBL_MODE_LBN 3
++ #define BUF_TBL_MODE_WIDTH 1
++#define SRM_RX_DC_CFG_REG_KER_OFST 0x610 /* SRAM receive descriptor cache
++ configuration register */
++#define SRM_RX_DC_CFG_REG_OFST 0x610 /* SRAM receive descriptor cache
++ configuration register */
++ #define SRM_RX_DC_BASE_ADR_LBN 0
++ #define SRM_RX_DC_BASE_ADR_WIDTH 21
++#define SRM_TX_DC_CFG_REG_KER_OFST 0x620 /* SRAM transmit descriptor cache
++ configuration register */
++#define SRM_TX_DC_CFG_REG_OFST 0x620 /* SRAM transmit descriptor cache
++ configuration register */
++ #define SRM_TX_DC_BASE_ADR_LBN 0
++ #define SRM_TX_DC_BASE_ADR_WIDTH 21
++#define SRM_CFG_REG_KER_OFST 0x630 /* SRAM configuration register */
++#define SRM_CFG_REG_OFST 0x630 /* SRAM configuration register */
++ #define SRAM_OOB_ADR_INTEN_LBN 5
++ #define SRAM_OOB_ADR_INTEN_WIDTH 1
++ #define SRAM_OOB_BUF_INTEN_LBN 4
++ #define SRAM_OOB_BUF_INTEN_WIDTH 1
++ #define SRAM_BT_INIT_EN_LBN 3
++ #define SRAM_BT_INIT_EN_WIDTH 1
++ #define SRM_NUM_BANK_LBN 2
++ #define SRM_NUM_BANK_WIDTH 1
++ #define SRM_BANK_SIZE_LBN 0
++ #define SRM_BANK_SIZE_WIDTH 2
++#define BUF_TBL_UPD_REG_KER_OFST 0x650 /* Buffer table update register */
++#define BUF_TBL_UPD_REG_OFST 0x650 /* Buffer table update register */
++ #define BUF_UPD_CMD_LBN 63
++ #define BUF_UPD_CMD_WIDTH 1
++ #define BUF_CLR_CMD_LBN 62
++ #define BUF_CLR_CMD_WIDTH 1
++ #define BUF_CLR_END_ID_LBN 32
++ #define BUF_CLR_END_ID_WIDTH 20
++ #define BUF_CLR_START_ID_LBN 0
++ #define BUF_CLR_START_ID_WIDTH 20
++#define SRM_UPD_EVQ_REG_KER_OFST 0x660 /* Buffer table update register */
++#define SRM_UPD_EVQ_REG_OFST 0x660 /* Buffer table update register */
++ #define SRM_UPD_EVQ_ID_LBN 0
++ #define SRM_UPD_EVQ_ID_WIDTH 12
++#define SRAM_PARITY_REG_KER_OFST 0x670 /* SRAM parity register. */
++#define SRAM_PARITY_REG_OFST 0x670 /* SRAM parity register. */
++ #define FORCE_SRAM_PERR_LBN 0
++ #define FORCE_SRAM_PERR_WIDTH 1
++
++#if FALCON_EXTENDED_P_BAR
++#define BUF_HALF_TBL_KER_OFST 0x18000 /* Buffer table in half buffer table
++ mode direct access by kernel driver */
++#else
++#define BUF_HALF_TBL_KER_OFST 0x8000 /* Buffer table in half buffer table
++ mode direct access by kernel driver */
++#endif
++
++
++#define BUF_HALF_TBL_OFST 0x800000 /* Buffer table in half buffer table mode
++ direct access by char driver */
++ #define BUF_ADR_HBUF_ODD_LBN 44
++ #define BUF_ADR_HBUF_ODD_WIDTH 20
++ #define BUF_OWNER_ID_HBUF_ODD_LBN 32
++ #define BUF_OWNER_ID_HBUF_ODD_WIDTH 12
++ #define BUF_ADR_HBUF_EVEN_LBN 12
++ #define BUF_ADR_HBUF_EVEN_WIDTH 20
++ #define BUF_OWNER_ID_HBUF_EVEN_LBN 0
++ #define BUF_OWNER_ID_HBUF_EVEN_WIDTH 12
++
++
++#if FALCON_EXTENDED_P_BAR
++#define BUF_FULL_TBL_KER_OFST 0x18000 /* Buffer table in full buffer table
++ mode direct access by kernel driver */
++#else
++#define BUF_FULL_TBL_KER_OFST 0x8000 /* Buffer table in full buffer table mode
++ direct access by kernel driver */
++#endif
++
++
++
++
++#define BUF_FULL_TBL_OFST 0x800000 /* Buffer table in full buffer table mode
++ direct access by char driver */
++ #define IP_DAT_BUF_SIZE_LBN 50
++ #define IP_DAT_BUF_SIZE_WIDTH 1
++ #define BUF_ADR_REGION_LBN 48
++ #define BUF_ADR_REGION_WIDTH 2
++ #define BUF_ADR_FBUF_LBN 14
++ #define BUF_ADR_FBUF_WIDTH 34
++ #define BUF_OWNER_ID_FBUF_LBN 0
++ #define BUF_OWNER_ID_FBUF_WIDTH 14
++#define SRM_DBG_REG_OFST 0x3000000 /* SRAM debug access */
++ #define SRM_DBG_LBN 0
++ #define SRM_DBG_WIDTH 64
++/*************---- RX Datapath Registers C Header ----*************/
++
++#define RX_CFG_REG_KER_OFST 0x800 /* Receive configuration register */
++#define RX_CFG_REG_OFST 0x800 /* Receive configuration register */
++
++#if !defined(FALCON_64K_RXFIFO) && !defined(FALCON_PRE_02020029)
++# if !defined(FALCON_128K_RXFIFO)
++# define FALCON_128K_RXFIFO
++# endif
++#endif
++
++#if defined(FALCON_128K_RXFIFO)
++
++/* new for B0 */
++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 48
++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++ #define RX_INGR_EN_B0_LBN 47
++ #define RX_INGR_EN_B0_WIDTH 1
++ #define RX_TOEP_IPV4_B0_LBN 46
++ #define RX_TOEP_IPV4_B0_WIDTH 1
++ #define RX_HASH_ALG_B0_LBN 45
++ #define RX_HASH_ALG_B0_WIDTH 1
++ #define RX_HASH_INSERT_HDR_B0_LBN 44
++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++ #define RX_DESC_PUSH_EN_B0_LBN 43
++ #define RX_DESC_PUSH_EN_B0_WIDTH 1
++ #define RX_RDW_PATCH_EN_LBN 42 /* Non head of line blocking */
++ #define RX_RDW_PATCH_EN_WIDTH 1
++ #define RX_PCI_BURST_SIZE_B0_LBN 39
++ #define RX_PCI_BURST_SIZE_B0_WIDTH 3
++ #define RX_OWNERR_CTL_B0_LBN 38
++ #define RX_OWNERR_CTL_B0_WIDTH 1
++ #define RX_XON_TX_TH_B0_LBN 33
++ #define RX_XON_TX_TH_B0_WIDTH 5
++ #define RX_XOFF_TX_TH_B0_LBN 28
++ #define RX_XOFF_TX_TH_B0_WIDTH 5
++ #define RX_USR_BUF_SIZE_B0_LBN 19
++ #define RX_USR_BUF_SIZE_B0_WIDTH 9
++ #define RX_XON_MAC_TH_B0_LBN 10
++ #define RX_XON_MAC_TH_B0_WIDTH 9
++ #define RX_XOFF_MAC_TH_B0_LBN 1
++ #define RX_XOFF_MAC_TH_B0_WIDTH 9
++ #define RX_XOFF_MAC_EN_B0_LBN 0
++ #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#elif !defined(FALCON_PRE_02020029)
++/* new for B0 */
++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 46
++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++ #define RX_INGR_EN_B0_LBN 45
++ #define RX_INGR_EN_B0_WIDTH 1
++ #define RX_TOEP_IPV4_B0_LBN 44
++ #define RX_TOEP_IPV4_B0_WIDTH 1
++ #define RX_HASH_ALG_B0_LBN 43
++ #define RX_HASH_ALG_B0_WIDTH 41
++ #define RX_HASH_INSERT_HDR_B0_LBN 42
++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++ #define RX_DESC_PUSH_EN_B0_LBN 41
++ #define RX_DESC_PUSH_EN_B0_WIDTH 1
++ #define RX_PCI_BURST_SIZE_B0_LBN 37
++ #define RX_PCI_BURST_SIZE_B0_WIDTH 3
++ #define RX_OWNERR_CTL_B0_LBN 36
++ #define RX_OWNERR_CTL_B0_WIDTH 1
++ #define RX_XON_TX_TH_B0_LBN 31
++ #define RX_XON_TX_TH_B0_WIDTH 5
++ #define RX_XOFF_TX_TH_B0_LBN 26
++ #define RX_XOFF_TX_TH_B0_WIDTH 5
++ #define RX_USR_BUF_SIZE_B0_LBN 17
++ #define RX_USR_BUF_SIZE_B0_WIDTH 9
++ #define RX_XON_MAC_TH_B0_LBN 9
++ #define RX_XON_MAC_TH_B0_WIDTH 8
++ #define RX_XOFF_MAC_TH_B0_LBN 1
++ #define RX_XOFF_MAC_TH_B0_WIDTH 8
++ #define RX_XOFF_MAC_EN_B0_LBN 0
++ #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#else
++/* new for B0 */
++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 44
++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++ #define RX_INGR_EN_B0_LBN 43
++ #define RX_INGR_EN_B0_WIDTH 1
++ #define RX_TOEP_IPV4_B0_LBN 42
++ #define RX_TOEP_IPV4_B0_WIDTH 1
++ #define RX_HASH_ALG_B0_LBN 41
++ #define RX_HASH_ALG_B0_WIDTH 41
++ #define RX_HASH_INSERT_HDR_B0_LBN 40
++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++ #define RX_DESC_PUSH_EN_B0_LBN 35
++ #define RX_DESC_PUSH_EN_B0_WIDTH 1
++ #define RX_PCI_BURST_SIZE_B0_LBN 35
++ #define RX_PCI_BURST_SIZE_B0_WIDTH 2
++ #define RX_OWNERR_CTL_B0_LBN 34
++ #define RX_OWNERR_CTL_B0_WIDTH 1
++ #define RX_XON_TX_TH_B0_LBN 29
++ #define RX_XON_TX_TH_B0_WIDTH 5
++ #define RX_XOFF_TX_TH_B0_LBN 24
++ #define RX_XOFF_TX_TH_B0_WIDTH 5
++ #define RX_USR_BUF_SIZE_B0_LBN 15
++ #define RX_USR_BUF_SIZE_B0_WIDTH 9
++ #define RX_XON_MAC_TH_B0_LBN 8
++ #define RX_XON_MAC_TH_B0_WIDTH 7
++ #define RX_XOFF_MAC_TH_B0_LBN 1
++ #define RX_XOFF_MAC_TH_B0_WIDTH 7
++ #define RX_XOFF_MAC_EN_B0_LBN 0
++ #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#endif
++
++/* A0/A1 */
++ #define RX_PUSH_EN_A1_LBN 35
++ #define RX_PUSH_EN_A1_WIDTH 1
++ #define RX_PCI_BURST_SIZE_A1_LBN 31
++ #define RX_PCI_BURST_SIZE_A1_WIDTH 3
++ #define RX_OWNERR_CTL_A1_LBN 30
++ #define RX_OWNERR_CTL_A1_WIDTH 1
++ #define RX_XON_TX_TH_A1_LBN 25
++ #define RX_XON_TX_TH_A1_WIDTH 5
++ #define RX_XOFF_TX_TH_A1_LBN 20
++ #define RX_XOFF_TX_TH_A1_WIDTH 5
++ #define RX_USR_BUF_SIZE_A1_LBN 11
++ #define RX_USR_BUF_SIZE_A1_WIDTH 9
++ #define RX_XON_MAC_TH_A1_LBN 6
++ #define RX_XON_MAC_TH_A1_WIDTH 5
++ #define RX_XOFF_MAC_TH_A1_LBN 1
++ #define RX_XOFF_MAC_TH_A1_WIDTH 5
++ #define RX_XOFF_MAC_EN_A1_LBN 0
++ #define RX_XOFF_MAC_EN_A1_WIDTH 1
++
++#define RX_FILTER_CTL_REG_OFST 0x810 /* Receive filter control registers */
++ #define SCATTER_ENBL_NO_MATCH_Q_B0_LBN 40
++ #define SCATTER_ENBL_NO_MATCH_Q_B0_WIDTH 1
++ #define UDP_FULL_SRCH_LIMIT_LBN 32
++ #define UDP_FULL_SRCH_LIMIT_WIDTH 8
++ #define NUM_KER_LBN 24
++ #define NUM_KER_WIDTH 2
++ #define UDP_WILD_SRCH_LIMIT_LBN 16
++ #define UDP_WILD_SRCH_LIMIT_WIDTH 8
++ #define TCP_WILD_SRCH_LIMIT_LBN 8
++ #define TCP_WILD_SRCH_LIMIT_WIDTH 8
++ #define TCP_FULL_SRCH_LIMIT_LBN 0
++ #define TCP_FULL_SRCH_LIMIT_WIDTH 8
++#define RX_FLUSH_DESCQ_REG_KER_OFST 0x820 /* Receive flush descriptor queue
++ register */
++#define RX_FLUSH_DESCQ_REG_OFST 0x820 /* Receive flush descriptor queue
++ register */
++ #define RX_FLUSH_DESCQ_CMD_LBN 24
++ #define RX_FLUSH_DESCQ_CMD_WIDTH 1
++ #define RX_FLUSH_EVQ_ID_LBN 12
++ #define RX_FLUSH_EVQ_ID_WIDTH 12
++ #define RX_FLUSH_DESCQ_LBN 0
++ #define RX_FLUSH_DESCQ_WIDTH 12
++#define RX_DESC_UPD_REG_KER_OFST 0x830 /* Kernel receive descriptor update
++ register. Page-mapped */
++#define RX_DESC_UPD_REG_PAGE4_OFST 0x8830 /* Char & user receive descriptor
++ update register. Page-mapped.
++ For lowest 1K queues. */
++#define RX_DESC_UPD_REG_PAGE123K_OFST 0x1000830 /* Char & user receive
++ descriptor update register.
++ Page-mapped. For upper
++ 3K queues. */
++ #define RX_DESC_WPTR_LBN 96
++ #define RX_DESC_WPTR_WIDTH 12
++ #define RX_DESC_PUSH_CMD_LBN 95
++ #define RX_DESC_PUSH_CMD_WIDTH 1
++ #define RX_DESC_LBN 0
++ #define RX_DESC_WIDTH 64
++ #define RX_KER_DESC_LBN 0
++ #define RX_KER_DESC_WIDTH 64
++ #define RX_USR_DESC_LBN 0
++ #define RX_USR_DESC_WIDTH 32
++#define RX_DC_CFG_REG_KER_OFST 0x840 /* Receive descriptor cache
++ configuration register */
++#define RX_DC_CFG_REG_OFST 0x840 /* Receive descriptor cache
++ configuration register */
++ #define RX_DC_SIZE_LBN 0
++ #define RX_DC_SIZE_WIDTH 2
++#define RX_DC_PF_WM_REG_KER_OFST 0x850 /* Receive descriptor cache pre-fetch
++ watermark register */
++#define RX_DC_PF_WM_REG_OFST 0x850 /* Receive descriptor cache pre-fetch
++ watermark register */
++ #define RX_DC_PF_LWM_LO_LBN 0
++ #define RX_DC_PF_LWM_LO_WIDTH 6
++
++#define RX_RSS_TKEY_B0_OFST 0x860 /* RSS Toeplitz hash key (B0 only) */
++
++#define RX_NODESC_DROP_REG 0x880
++ #define RX_NODESC_DROP_CNT_LBN 0
++ #define RX_NODESC_DROP_CNT_WIDTH 16
++
++#define XM_TX_CFG_REG_OFST 0x1230
++ #define XM_AUTO_PAD_LBN 5
++ #define XM_AUTO_PAD_WIDTH 1
++
++#define RX_FILTER_TBL0_OFST 0xF00000 /* Receive filter table - even entries */
++ #define RSS_EN_0_B0_LBN 110
++ #define RSS_EN_0_B0_WIDTH 1
++ #define SCATTER_EN_0_B0_LBN 109
++ #define SCATTER_EN_0_B0_WIDTH 1
++ #define TCP_UDP_0_LBN 108
++ #define TCP_UDP_0_WIDTH 1
++ #define RXQ_ID_0_LBN 96
++ #define RXQ_ID_0_WIDTH 12
++ #define DEST_IP_0_LBN 64
++ #define DEST_IP_0_WIDTH 32
++ #define DEST_PORT_TCP_0_LBN 48
++ #define DEST_PORT_TCP_0_WIDTH 16
++ #define SRC_IP_0_LBN 16
++ #define SRC_IP_0_WIDTH 32
++ #define SRC_TCP_DEST_UDP_0_LBN 0
++ #define SRC_TCP_DEST_UDP_0_WIDTH 16
++#define RX_FILTER_TBL1_OFST 0xF00010 /* Receive filter table - odd entries */
++ #define RSS_EN_1_B0_LBN 110
++ #define RSS_EN_1_B0_WIDTH 1
++ #define SCATTER_EN_1_B0_LBN 109
++ #define SCATTER_EN_1_B0_WIDTH 1
++ #define TCP_UDP_1_LBN 108
++ #define TCP_UDP_1_WIDTH 1
++ #define RXQ_ID_1_LBN 96
++ #define RXQ_ID_1_WIDTH 12
++ #define DEST_IP_1_LBN 64
++ #define DEST_IP_1_WIDTH 32
++ #define DEST_PORT_TCP_1_LBN 48
++ #define DEST_PORT_TCP_1_WIDTH 16
++ #define SRC_IP_1_LBN 16
++ #define SRC_IP_1_WIDTH 32
++ #define SRC_TCP_DEST_UDP_1_LBN 0
++ #define SRC_TCP_DEST_UDP_1_WIDTH 16
++
++#if FALCON_EXTENDED_P_BAR
++#define RX_DESC_PTR_TBL_KER_OFST 0x11800 /* Receive descriptor pointer
++ kernel access */
++#else
++#define RX_DESC_PTR_TBL_KER_OFST 0x1800 /* Receive descriptor pointer
++ kernel access */
++#endif
++
++
++#define RX_DESC_PTR_TBL_OFST 0xF40000 /* Receive descriptor pointer table */
++ #define RX_ISCSI_DDIG_EN_LBN 88
++ #define RX_ISCSI_DDIG_EN_WIDTH 1
++ #define RX_ISCSI_HDIG_EN_LBN 87
++ #define RX_ISCSI_HDIG_EN_WIDTH 1
++ #define RX_DESC_PREF_ACT_LBN 86
++ #define RX_DESC_PREF_ACT_WIDTH 1
++ #define RX_DC_HW_RPTR_LBN 80
++ #define RX_DC_HW_RPTR_WIDTH 6
++ #define RX_DESCQ_HW_RPTR_LBN 68
++ #define RX_DESCQ_HW_RPTR_WIDTH 12
++ #define RX_DESCQ_SW_WPTR_LBN 56
++ #define RX_DESCQ_SW_WPTR_WIDTH 12
++ #define RX_DESCQ_BUF_BASE_ID_LBN 36
++ #define RX_DESCQ_BUF_BASE_ID_WIDTH 20
++ #define RX_DESCQ_EVQ_ID_LBN 24
++ #define RX_DESCQ_EVQ_ID_WIDTH 12
++ #define RX_DESCQ_OWNER_ID_LBN 10
++ #define RX_DESCQ_OWNER_ID_WIDTH 14
++ #define RX_DESCQ_LABEL_LBN 5
++ #define RX_DESCQ_LABEL_WIDTH 5
++ #define RX_DESCQ_SIZE_LBN 3
++ #define RX_DESCQ_SIZE_WIDTH 2
++ #define RX_DESCQ_TYPE_LBN 2
++ #define RX_DESCQ_TYPE_WIDTH 1
++ #define RX_DESCQ_JUMBO_LBN 1
++ #define RX_DESCQ_JUMBO_WIDTH 1
++ #define RX_DESCQ_EN_LBN 0
++ #define RX_DESCQ_EN_WIDTH 1
++
++
++#define RX_RSS_INDIR_TBL_B0_OFST 0xFB0000 /* RSS indirection table (B0 only) */
++ #define RX_RSS_INDIR_ENT_B0_LBN 0
++ #define RX_RSS_INDIR_ENT_B0_WIDTH 6
++
++/*************---- TX Datapath Registers C Header ----*************/
++#define TX_FLUSH_DESCQ_REG_KER_OFST 0xA00 /* Transmit flush descriptor
++ queue register */
++#define TX_FLUSH_DESCQ_REG_OFST 0xA00 /* Transmit flush descriptor queue
++ register */
++ #define TX_FLUSH_DESCQ_CMD_LBN 12
++ #define TX_FLUSH_DESCQ_CMD_WIDTH 1
++ #define TX_FLUSH_DESCQ_LBN 0
++ #define TX_FLUSH_DESCQ_WIDTH 12
++#define TX_DESC_UPD_REG_KER_OFST 0xA10 /* Kernel transmit descriptor update
++ register. Page-mapped */
++#define TX_DESC_UPD_REG_PAGE4_OFST 0x8A10 /* Char & user transmit descriptor
++ update register. Page-mapped */
++#define TX_DESC_UPD_REG_PAGE123K_OFST 0x1000A10 /* Char & user transmit
++ descriptor update register.
++ Page-mapped */
++ #define TX_DESC_WPTR_LBN 96
++ #define TX_DESC_WPTR_WIDTH 12
++ #define TX_DESC_PUSH_CMD_LBN 95
++ #define TX_DESC_PUSH_CMD_WIDTH 1
++ #define TX_DESC_LBN 0
++ #define TX_DESC_WIDTH 95
++ #define TX_KER_DESC_LBN 0
++ #define TX_KER_DESC_WIDTH 64
++ #define TX_USR_DESC_LBN 0
++ #define TX_USR_DESC_WIDTH 64
++#define TX_DC_CFG_REG_KER_OFST 0xA20 /* Transmit descriptor cache
++ configuration register */
++#define TX_DC_CFG_REG_OFST 0xA20 /* Transmit descriptor cache configuration
++ register */
++ #define TX_DC_SIZE_LBN 0
++ #define TX_DC_SIZE_WIDTH 2
++
++#if FALCON_EXTENDED_P_BAR
++#define TX_DESC_PTR_TBL_KER_OFST 0x11900 /* Transmit descriptor pointer. */
++#else
++#define TX_DESC_PTR_TBL_KER_OFST 0x1900 /* Transmit descriptor pointer. */
++#endif
++
++
++#define TX_DESC_PTR_TBL_OFST 0xF50000 /* Transmit descriptor pointer */
++ #define TX_NON_IP_DROP_DIS_B0_LBN 91
++ #define TX_NON_IP_DROP_DIS_B0_WIDTH 1
++ #define TX_IP_CHKSM_DIS_B0_LBN 90
++ #define TX_IP_CHKSM_DIS_B0_WIDTH 1
++ #define TX_TCP_CHKSM_DIS_B0_LBN 89
++ #define TX_TCP_CHKSM_DIS_B0_WIDTH 1
++ #define TX_DESCQ_EN_LBN 88
++ #define TX_DESCQ_EN_WIDTH 1
++ #define TX_ISCSI_DDIG_EN_LBN 87
++ #define TX_ISCSI_DDIG_EN_WIDTH 1
++ #define TX_ISCSI_HDIG_EN_LBN 86
++ #define TX_ISCSI_HDIG_EN_WIDTH 1
++ #define TX_DC_HW_RPTR_LBN 80
++ #define TX_DC_HW_RPTR_WIDTH 6
++ #define TX_DESCQ_HW_RPTR_LBN 68
++ #define TX_DESCQ_HW_RPTR_WIDTH 12
++ #define TX_DESCQ_SW_WPTR_LBN 56
++ #define TX_DESCQ_SW_WPTR_WIDTH 12
++ #define TX_DESCQ_BUF_BASE_ID_LBN 36
++ #define TX_DESCQ_BUF_BASE_ID_WIDTH 20
++ #define TX_DESCQ_EVQ_ID_LBN 24
++ #define TX_DESCQ_EVQ_ID_WIDTH 12
++ #define TX_DESCQ_OWNER_ID_LBN 10
++ #define TX_DESCQ_OWNER_ID_WIDTH 14
++ #define TX_DESCQ_LABEL_LBN 5
++ #define TX_DESCQ_LABEL_WIDTH 5
++ #define TX_DESCQ_SIZE_LBN 3
++ #define TX_DESCQ_SIZE_WIDTH 2
++ #define TX_DESCQ_TYPE_LBN 1
++ #define TX_DESCQ_TYPE_WIDTH 2
++ #define TX_DESCQ_FLUSH_LBN 0
++ #define TX_DESCQ_FLUSH_WIDTH 1
++#define TX_CFG_REG_KER_OFST 0xA50 /* Transmit configuration register */
++#define TX_CFG_REG_OFST 0xA50 /* Transmit configuration register */
++ #define TX_IP_ID_P1_OFS_LBN 32
++ #define TX_IP_ID_P1_OFS_WIDTH 15
++ #define TX_IP_ID_P0_OFS_LBN 16
++ #define TX_IP_ID_P0_OFS_WIDTH 15
++ #define TX_TURBO_EN_LBN 3
++ #define TX_TURBO_EN_WIDTH 1
++ #define TX_OWNERR_CTL_LBN 2
++ #define TX_OWNERR_CTL_WIDTH 2
++ #define TX_NON_IP_DROP_DIS_LBN 1
++ #define TX_NON_IP_DROP_DIS_WIDTH 1
++ #define TX_IP_ID_REP_EN_LBN 0
++ #define TX_IP_ID_REP_EN_WIDTH 1
++#define TX_RESERVED_REG_KER_OFST 0xA80 /* Transmit configuration register */
++#define TX_RESERVED_REG_OFST 0xA80 /* Transmit configuration register */
++ #define TX_CSR_PUSH_EN_LBN 89
++ #define TX_CSR_PUSH_EN_WIDTH 1
++ #define TX_RX_SPACER_LBN 64
++ #define TX_RX_SPACER_WIDTH 8
++ #define TX_SW_EV_EN_LBN 59
++ #define TX_SW_EV_EN_WIDTH 1
++ #define TX_RX_SPACER_EN_LBN 57
++ #define TX_RX_SPACER_EN_WIDTH 1
++ #define TX_CSR_PREF_WD_TMR_LBN 24
++ #define TX_CSR_PREF_WD_TMR_WIDTH 16
++ #define TX_CSR_ONLY1TAG_LBN 21
++ #define TX_CSR_ONLY1TAG_WIDTH 1
++ #define TX_PREF_THRESHOLD_LBN 19
++ #define TX_PREF_THRESHOLD_WIDTH 2
++ #define TX_ONE_PKT_PER_Q_LBN 18
++ #define TX_ONE_PKT_PER_Q_WIDTH 1
++ #define TX_DIS_NON_IP_EV_LBN 17
++ #define TX_DIS_NON_IP_EV_WIDTH 1
++ #define TX_DMA_SPACER_LBN 8
++ #define TX_DMA_SPACER_WIDTH 8
++ #define TX_FLUSH_MIN_LEN_EN_B0_LBN 7
++ #define TX_FLUSH_MIN_LEN_EN_B0_WIDTH 1
++ #define TX_TCP_DIS_A1_LBN 7
++ #define TX_TCP_DIS_A1_WIDTH 1
++ #define TX_IP_DIS_A1_LBN 6
++ #define TX_IP_DIS_A1_WIDTH 1
++ #define TX_MAX_CPL_LBN 2
++ #define TX_MAX_CPL_WIDTH 2
++ #define TX_MAX_PREF_LBN 0
++ #define TX_MAX_PREF_WIDTH 2
++#define TX_VLAN_REG_OFST 0xAE0 /* Transmit VLAN tag register */
++ #define TX_VLAN_EN_LBN 127
++ #define TX_VLAN_EN_WIDTH 1
++ #define TX_VLAN7_PORT1_EN_LBN 125
++ #define TX_VLAN7_PORT1_EN_WIDTH 1
++ #define TX_VLAN7_PORT0_EN_LBN 124
++ #define TX_VLAN7_PORT0_EN_WIDTH 1
++ #define TX_VLAN7_LBN 112
++ #define TX_VLAN7_WIDTH 12
++ #define TX_VLAN6_PORT1_EN_LBN 109
++ #define TX_VLAN6_PORT1_EN_WIDTH 1
++ #define TX_VLAN6_PORT0_EN_LBN 108
++ #define TX_VLAN6_PORT0_EN_WIDTH 1
++ #define TX_VLAN6_LBN 96
++ #define TX_VLAN6_WIDTH 12
++ #define TX_VLAN5_PORT1_EN_LBN 93
++ #define TX_VLAN5_PORT1_EN_WIDTH 1
++ #define TX_VLAN5_PORT0_EN_LBN 92
++ #define TX_VLAN5_PORT0_EN_WIDTH 1
++ #define TX_VLAN5_LBN 80
++ #define TX_VLAN5_WIDTH 12
++ #define TX_VLAN4_PORT1_EN_LBN 77
++ #define TX_VLAN4_PORT1_EN_WIDTH 1
++ #define TX_VLAN4_PORT0_EN_LBN 76
++ #define TX_VLAN4_PORT0_EN_WIDTH 1
++ #define TX_VLAN4_LBN 64
++ #define TX_VLAN4_WIDTH 12
++ #define TX_VLAN3_PORT1_EN_LBN 61
++ #define TX_VLAN3_PORT1_EN_WIDTH 1
++ #define TX_VLAN3_PORT0_EN_LBN 60
++ #define TX_VLAN3_PORT0_EN_WIDTH 1
++ #define TX_VLAN3_LBN 48
++ #define TX_VLAN3_WIDTH 12
++ #define TX_VLAN2_PORT1_EN_LBN 45
++ #define TX_VLAN2_PORT1_EN_WIDTH 1
++ #define TX_VLAN2_PORT0_EN_LBN 44
++ #define TX_VLAN2_PORT0_EN_WIDTH 1
++ #define TX_VLAN2_LBN 32
++ #define TX_VLAN2_WIDTH 12
++ #define TX_VLAN1_PORT1_EN_LBN 29
++ #define TX_VLAN1_PORT1_EN_WIDTH 1
++ #define TX_VLAN1_PORT0_EN_LBN 28
++ #define TX_VLAN1_PORT0_EN_WIDTH 1
++ #define TX_VLAN1_LBN 16
++ #define TX_VLAN1_WIDTH 12
++ #define TX_VLAN0_PORT1_EN_LBN 13
++ #define TX_VLAN0_PORT1_EN_WIDTH 1
++ #define TX_VLAN0_PORT0_EN_LBN 12
++ #define TX_VLAN0_PORT0_EN_WIDTH 1
++ #define TX_VLAN0_LBN 0
++ #define TX_VLAN0_WIDTH 12
++#define TX_FIL_CTL_REG_OFST 0xAF0 /* Transmit filter control register */
++ #define TX_MADR1_FIL_EN_LBN 65
++ #define TX_MADR1_FIL_EN_WIDTH 1
++ #define TX_MADR0_FIL_EN_LBN 64
++ #define TX_MADR0_FIL_EN_WIDTH 1
++ #define TX_IPFIL31_PORT1_EN_LBN 63
++ #define TX_IPFIL31_PORT1_EN_WIDTH 1
++ #define TX_IPFIL31_PORT0_EN_LBN 62
++ #define TX_IPFIL31_PORT0_EN_WIDTH 1
++ #define TX_IPFIL30_PORT1_EN_LBN 61
++ #define TX_IPFIL30_PORT1_EN_WIDTH 1
++ #define TX_IPFIL30_PORT0_EN_LBN 60
++ #define TX_IPFIL30_PORT0_EN_WIDTH 1
++ #define TX_IPFIL29_PORT1_EN_LBN 59
++ #define TX_IPFIL29_PORT1_EN_WIDTH 1
++ #define TX_IPFIL29_PORT0_EN_LBN 58
++ #define TX_IPFIL29_PORT0_EN_WIDTH 1
++ #define TX_IPFIL28_PORT1_EN_LBN 57
++ #define TX_IPFIL28_PORT1_EN_WIDTH 1
++ #define TX_IPFIL28_PORT0_EN_LBN 56
++ #define TX_IPFIL28_PORT0_EN_WIDTH 1
++ #define TX_IPFIL27_PORT1_EN_LBN 55
++ #define TX_IPFIL27_PORT1_EN_WIDTH 1
++ #define TX_IPFIL27_PORT0_EN_LBN 54
++ #define TX_IPFIL27_PORT0_EN_WIDTH 1
++ #define TX_IPFIL26_PORT1_EN_LBN 53
++ #define TX_IPFIL26_PORT1_EN_WIDTH 1
++ #define TX_IPFIL26_PORT0_EN_LBN 52
++ #define TX_IPFIL26_PORT0_EN_WIDTH 1
++ #define TX_IPFIL25_PORT1_EN_LBN 51
++ #define TX_IPFIL25_PORT1_EN_WIDTH 1
++ #define TX_IPFIL25_PORT0_EN_LBN 50
++ #define TX_IPFIL25_PORT0_EN_WIDTH 1
++ #define TX_IPFIL24_PORT1_EN_LBN 49
++ #define TX_IPFIL24_PORT1_EN_WIDTH 1
++ #define TX_IPFIL24_PORT0_EN_LBN 48
++ #define TX_IPFIL24_PORT0_EN_WIDTH 1
++ #define TX_IPFIL23_PORT1_EN_LBN 47
++ #define TX_IPFIL23_PORT1_EN_WIDTH 1
++ #define TX_IPFIL23_PORT0_EN_LBN 46
++ #define TX_IPFIL23_PORT0_EN_WIDTH 1
++ #define TX_IPFIL22_PORT1_EN_LBN 45
++ #define TX_IPFIL22_PORT1_EN_WIDTH 1
++ #define TX_IPFIL22_PORT0_EN_LBN 44
++ #define TX_IPFIL22_PORT0_EN_WIDTH 1
++ #define TX_IPFIL21_PORT1_EN_LBN 43
++ #define TX_IPFIL21_PORT1_EN_WIDTH 1
++ #define TX_IPFIL21_PORT0_EN_LBN 42
++ #define TX_IPFIL21_PORT0_EN_WIDTH 1
++ #define TX_IPFIL20_PORT1_EN_LBN 41
++ #define TX_IPFIL20_PORT1_EN_WIDTH 1
++ #define TX_IPFIL20_PORT0_EN_LBN 40
++ #define TX_IPFIL20_PORT0_EN_WIDTH 1
++ #define TX_IPFIL19_PORT1_EN_LBN 39
++ #define TX_IPFIL19_PORT1_EN_WIDTH 1
++ #define TX_IPFIL19_PORT0_EN_LBN 38
++ #define TX_IPFIL19_PORT0_EN_WIDTH 1
++ #define TX_IPFIL18_PORT1_EN_LBN 37
++ #define TX_IPFIL18_PORT1_EN_WIDTH 1
++ #define TX_IPFIL18_PORT0_EN_LBN 36
++ #define TX_IPFIL18_PORT0_EN_WIDTH 1
++ #define TX_IPFIL17_PORT1_EN_LBN 35
++ #define TX_IPFIL17_PORT1_EN_WIDTH 1
++ #define TX_IPFIL17_PORT0_EN_LBN 34
++ #define TX_IPFIL17_PORT0_EN_WIDTH 1
++ #define TX_IPFIL16_PORT1_EN_LBN 33
++ #define TX_IPFIL16_PORT1_EN_WIDTH 1
++ #define TX_IPFIL16_PORT0_EN_LBN 32
++ #define TX_IPFIL16_PORT0_EN_WIDTH 1
++ #define TX_IPFIL15_PORT1_EN_LBN 31
++ #define TX_IPFIL15_PORT1_EN_WIDTH 1
++ #define TX_IPFIL15_PORT0_EN_LBN 30
++ #define TX_IPFIL15_PORT0_EN_WIDTH 1
++ #define TX_IPFIL14_PORT1_EN_LBN 29
++ #define TX_IPFIL14_PORT1_EN_WIDTH 1
++ #define TX_IPFIL14_PORT0_EN_LBN 28
++ #define TX_IPFIL14_PORT0_EN_WIDTH 1
++ #define TX_IPFIL13_PORT1_EN_LBN 27
++ #define TX_IPFIL13_PORT1_EN_WIDTH 1
++ #define TX_IPFIL13_PORT0_EN_LBN 26
++ #define TX_IPFIL13_PORT0_EN_WIDTH 1
++ #define TX_IPFIL12_PORT1_EN_LBN 25
++ #define TX_IPFIL12_PORT1_EN_WIDTH 1
++ #define TX_IPFIL12_PORT0_EN_LBN 24
++ #define TX_IPFIL12_PORT0_EN_WIDTH 1
++ #define TX_IPFIL11_PORT1_EN_LBN 23
++ #define TX_IPFIL11_PORT1_EN_WIDTH 1
++ #define TX_IPFIL11_PORT0_EN_LBN 22
++ #define TX_IPFIL11_PORT0_EN_WIDTH 1
++ #define TX_IPFIL10_PORT1_EN_LBN 21
++ #define TX_IPFIL10_PORT1_EN_WIDTH 1
++ #define TX_IPFIL10_PORT0_EN_LBN 20
++ #define TX_IPFIL10_PORT0_EN_WIDTH 1
++ #define TX_IPFIL9_PORT1_EN_LBN 19
++ #define TX_IPFIL9_PORT1_EN_WIDTH 1
++ #define TX_IPFIL9_PORT0_EN_LBN 18
++ #define TX_IPFIL9_PORT0_EN_WIDTH 1
++ #define TX_IPFIL8_PORT1_EN_LBN 17
++ #define TX_IPFIL8_PORT1_EN_WIDTH 1
++ #define TX_IPFIL8_PORT0_EN_LBN 16
++ #define TX_IPFIL8_PORT0_EN_WIDTH 1
++ #define TX_IPFIL7_PORT1_EN_LBN 15
++ #define TX_IPFIL7_PORT1_EN_WIDTH 1
++ #define TX_IPFIL7_PORT0_EN_LBN 14
++ #define TX_IPFIL7_PORT0_EN_WIDTH 1
++ #define TX_IPFIL6_PORT1_EN_LBN 13
++ #define TX_IPFIL6_PORT1_EN_WIDTH 1
++ #define TX_IPFIL6_PORT0_EN_LBN 12
++ #define TX_IPFIL6_PORT0_EN_WIDTH 1
++ #define TX_IPFIL5_PORT1_EN_LBN 11
++ #define TX_IPFIL5_PORT1_EN_WIDTH 1
++ #define TX_IPFIL5_PORT0_EN_LBN 10
++ #define TX_IPFIL5_PORT0_EN_WIDTH 1
++ #define TX_IPFIL4_PORT1_EN_LBN 9
++ #define TX_IPFIL4_PORT1_EN_WIDTH 1
++ #define TX_IPFIL4_PORT0_EN_LBN 8
++ #define TX_IPFIL4_PORT0_EN_WIDTH 1
++ #define TX_IPFIL3_PORT1_EN_LBN 7
++ #define TX_IPFIL3_PORT1_EN_WIDTH 1
++ #define TX_IPFIL3_PORT0_EN_LBN 6
++ #define TX_IPFIL3_PORT0_EN_WIDTH 1
++ #define TX_IPFIL2_PORT1_EN_LBN 5
++ #define TX_IPFIL2_PORT1_EN_WIDTH 1
++ #define TX_IPFIL2_PORT0_EN_LBN 4
++ #define TX_IPFIL2_PORT0_EN_WIDTH 1
++ #define TX_IPFIL1_PORT1_EN_LBN 3
++ #define TX_IPFIL1_PORT1_EN_WIDTH 1
++ #define TX_IPFIL1_PORT0_EN_LBN 2
++ #define TX_IPFIL1_PORT0_EN_WIDTH 1
++ #define TX_IPFIL0_PORT1_EN_LBN 1
++ #define TX_IPFIL0_PORT1_EN_WIDTH 1
++ #define TX_IPFIL0_PORT0_EN_LBN 0
++ #define TX_IPFIL0_PORT0_EN_WIDTH 1
++#define TX_IPFIL_TBL_OFST 0xB00 /* Transmit IP source address filter table */
++ #define TX_IPFIL_MASK_LBN 32
++ #define TX_IPFIL_MASK_WIDTH 32
++ #define TX_IP_SRC_ADR_LBN 0
++ #define TX_IP_SRC_ADR_WIDTH 32
++#define TX_PACE_REG_A1_OFST 0xF80000 /* Transmit pace control register */
++#define TX_PACE_REG_B0_OFST 0xA90 /* Transmit pace control register */
++ #define TX_PACE_SB_AF_LBN 19
++ #define TX_PACE_SB_AF_WIDTH 10
++ #define TX_PACE_SB_NOTAF_LBN 9
++ #define TX_PACE_SB_NOTAF_WIDTH 10
++ #define TX_PACE_FB_BASE_LBN 5
++ #define TX_PACE_FB_BASE_WIDTH 4
++ #define TX_PACE_BIN_TH_LBN 0
++ #define TX_PACE_BIN_TH_WIDTH 5
++#define TX_PACE_TBL_A1_OFST 0xF80040 /* Transmit pacing table */
++#define TX_PACE_TBL_FIRST_QUEUE_A1 4
++#define TX_PACE_TBL_B0_OFST 0xF80000 /* Transmit pacing table */
++#define TX_PACE_TBL_FIRST_QUEUE_B0 0
++ #define TX_PACE_LBN 0
++ #define TX_PACE_WIDTH 5
++
++/*************---- EE/Flash Registers C Header ----*************/
++#define EE_SPI_HCMD_REG_KER_OFST 0x100 /* SPI host command register */
++#define EE_SPI_HCMD_REG_OFST 0x100 /* SPI host command register */
++ #define EE_SPI_HCMD_CMD_EN_LBN 31
++ #define EE_SPI_HCMD_CMD_EN_WIDTH 1
++ #define EE_WR_TIMER_ACTIVE_LBN 28
++ #define EE_WR_TIMER_ACTIVE_WIDTH 1
++ #define EE_SPI_HCMD_SF_SEL_LBN 24
++ #define EE_SPI_HCMD_SF_SEL_WIDTH 1
++ #define EE_SPI_HCMD_DABCNT_LBN 16
++ #define EE_SPI_HCMD_DABCNT_WIDTH 5
++ #define EE_SPI_HCMD_READ_LBN 15
++ #define EE_SPI_HCMD_READ_WIDTH 1
++ #define EE_SPI_HCMD_DUBCNT_LBN 12
++ #define EE_SPI_HCMD_DUBCNT_WIDTH 2
++ #define EE_SPI_HCMD_ADBCNT_LBN 8
++ #define EE_SPI_HCMD_ADBCNT_WIDTH 2
++ #define EE_SPI_HCMD_ENC_LBN 0
++ #define EE_SPI_HCMD_ENC_WIDTH 8
++#define EE_SPI_HADR_REG_KER_OFST 0X110 /* SPI host address register */
++#define EE_SPI_HADR_REG_OFST 0X110 /* SPI host address register */
++ #define EE_SPI_HADR_DUBYTE_LBN 24
++ #define EE_SPI_HADR_DUBYTE_WIDTH 8
++ #define EE_SPI_HADR_ADR_LBN 0
++ #define EE_SPI_HADR_ADR_WIDTH 24
++#define EE_SPI_HDATA_REG_KER_OFST 0x120 /* SPI host data register */
++#define EE_SPI_HDATA_REG_OFST 0x120 /* SPI host data register */
++ #define EE_SPI_HDATA3_LBN 96
++ #define EE_SPI_HDATA3_WIDTH 32
++ #define EE_SPI_HDATA2_LBN 64
++ #define EE_SPI_HDATA2_WIDTH 32
++ #define EE_SPI_HDATA1_LBN 32
++ #define EE_SPI_HDATA1_WIDTH 32
++ #define EE_SPI_HDATA0_LBN 0
++ #define EE_SPI_HDATA0_WIDTH 32
++#define EE_BASE_PAGE_REG_KER_OFST 0x130 /* Expansion ROM base mirror register */
++#define EE_BASE_PAGE_REG_OFST 0x130 /* Expansion ROM base mirror register */
++ #define EE_EXP_ROM_WINDOW_BASE_LBN 16
++ #define EE_EXP_ROM_WINDOW_BASE_WIDTH 13
++ #define EE_EXPROM_MASK_LBN 0
++ #define EE_EXPROM_MASK_WIDTH 13
++#define EE_VPD_CFG0_REG_KER_OFST 0X140 /* SPI/VPD configuration register */
++#define EE_VPD_CFG0_REG_OFST 0X140 /* SPI/VPD configuration register */
++ #define EE_SF_FASTRD_EN_LBN 127
++ #define EE_SF_FASTRD_EN_WIDTH 1
++ #define EE_SF_CLOCK_DIV_LBN 120
++ #define EE_SF_CLOCK_DIV_WIDTH 7
++ #define EE_VPD_WIP_POLL_LBN 119
++ #define EE_VPD_WIP_POLL_WIDTH 1
++ #define EE_VPDW_LENGTH_LBN 80
++ #define EE_VPDW_LENGTH_WIDTH 15
++ #define EE_VPDW_BASE_LBN 64
++ #define EE_VPDW_BASE_WIDTH 15
++ #define EE_VPD_WR_CMD_EN_LBN 56
++ #define EE_VPD_WR_CMD_EN_WIDTH 8
++ #define EE_VPD_BASE_LBN 32
++ #define EE_VPD_BASE_WIDTH 24
++ #define EE_VPD_LENGTH_LBN 16
++ #define EE_VPD_LENGTH_WIDTH 13
++ #define EE_VPD_AD_SIZE_LBN 8
++ #define EE_VPD_AD_SIZE_WIDTH 5
++ #define EE_VPD_ACCESS_ON_LBN 5
++ #define EE_VPD_ACCESS_ON_WIDTH 1
++#define EE_VPD_SW_CNTL_REG_KER_OFST 0X150 /* VPD access SW control register */
++#define EE_VPD_SW_CNTL_REG_OFST 0X150 /* VPD access SW control register */
++ #define EE_VPD_CYCLE_PENDING_LBN 31
++ #define EE_VPD_CYCLE_PENDING_WIDTH 1
++ #define EE_VPD_CYC_WRITE_LBN 28
++ #define EE_VPD_CYC_WRITE_WIDTH 1
++ #define EE_VPD_CYC_ADR_LBN 0
++ #define EE_VPD_CYC_ADR_WIDTH 15
++#define EE_VPD_SW_DATA_REG_KER_OFST 0x160 /* VPD access SW data register */
++#define EE_VPD_SW_DATA_REG_OFST 0x160 /* VPD access SW data register */
++ #define EE_VPD_CYC_DAT_LBN 0
++ #define EE_VPD_CYC_DAT_WIDTH 32
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,75 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) descriptor
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*************---- Descriptors C Headers ----*************/
++/* Receive Kernel IP Descriptor */
++ #define RX_KER_BUF_SIZE_LBN 48
++ #define RX_KER_BUF_SIZE_WIDTH 14
++ #define RX_KER_BUF_REGION_LBN 46
++ #define RX_KER_BUF_REGION_WIDTH 2
++ #define RX_KER_BUF_REGION0_DECODE 0
++ #define RX_KER_BUF_REGION1_DECODE 1
++ #define RX_KER_BUF_REGION2_DECODE 2
++ #define RX_KER_BUF_REGION3_DECODE 3
++ #define RX_KER_BUF_ADR_LBN 0
++ #define RX_KER_BUF_ADR_WIDTH 46
++/* Receive User IP Descriptor */
++ #define RX_USR_2BYTE_OFS_LBN 20
++ #define RX_USR_2BYTE_OFS_WIDTH 12
++ #define RX_USR_BUF_ID_LBN 0
++ #define RX_USR_BUF_ID_WIDTH 20
++/* Transmit Kernel IP Descriptor */
++ #define TX_KER_PORT_LBN 63
++ #define TX_KER_PORT_WIDTH 1
++ #define TX_KER_CONT_LBN 62
++ #define TX_KER_CONT_WIDTH 1
++ #define TX_KER_BYTE_CNT_LBN 48
++ #define TX_KER_BYTE_CNT_WIDTH 14
++ #define TX_KER_BUF_REGION_LBN 46
++ #define TX_KER_BUF_REGION_WIDTH 2
++ #define TX_KER_BUF_REGION0_DECODE 0
++ #define TX_KER_BUF_REGION1_DECODE 1
++ #define TX_KER_BUF_REGION2_DECODE 2
++ #define TX_KER_BUF_REGION3_DECODE 3
++ #define TX_KER_BUF_ADR_LBN 0
++ #define TX_KER_BUF_ADR_WIDTH 46
++/* Transmit User IP Descriptor */
++ #define TX_USR_PORT_LBN 47
++ #define TX_USR_PORT_WIDTH 1
++ #define TX_USR_CONT_LBN 46
++ #define TX_USR_CONT_WIDTH 1
++ #define TX_USR_BYTE_CNT_LBN 33
++ #define TX_USR_BYTE_CNT_WIDTH 13
++ #define TX_USR_BUF_ID_LBN 13
++ #define TX_USR_BUF_ID_WIDTH 20
++ #define TX_USR_BYTE_OFS_LBN 0
++ #define TX_USR_BYTE_OFS_WIDTH 13
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,155 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) event
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*************---- Events Format C Header ----*************/
++/*************---- Event entry ----*************/
++ #define EV_CODE_LBN 60
++ #define EV_CODE_WIDTH 4
++ #define RX_IP_EV_DECODE 0
++ #define TX_IP_EV_DECODE 2
++ #define DRIVER_EV_DECODE 5
++ #define GLOBAL_EV_DECODE 6
++ #define DRV_GEN_EV_DECODE 7
++ #define EV_DATA_LBN 0
++ #define EV_DATA_WIDTH 60
++/******---- Receive IP events for both Kernel & User event queues ----******/
++ #define RX_EV_PKT_OK_LBN 56
++ #define RX_EV_PKT_OK_WIDTH 1
++ #define RX_EV_BUF_OWNER_ID_ERR_LBN 54
++ #define RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++ #define RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
++ #define RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
++ #define RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
++ #define RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
++ #define RX_EV_ETH_CRC_ERR_LBN 50
++ #define RX_EV_ETH_CRC_ERR_WIDTH 1
++ #define RX_EV_FRM_TRUNC_LBN 49
++ #define RX_EV_FRM_TRUNC_WIDTH 1
++ #define RX_EV_DRIB_NIB_LBN 48
++ #define RX_EV_DRIB_NIB_WIDTH 1
++ #define RX_EV_TOBE_DISC_LBN 47
++ #define RX_EV_TOBE_DISC_WIDTH 1
++ #define RX_EV_PKT_TYPE_LBN 44
++ #define RX_EV_PKT_TYPE_WIDTH 3
++ #define RX_EV_PKT_TYPE_ETH_DECODE 0
++ #define RX_EV_PKT_TYPE_LLC_DECODE 1
++ #define RX_EV_PKT_TYPE_JUMBO_DECODE 2
++ #define RX_EV_PKT_TYPE_VLAN_DECODE 3
++ #define RX_EV_PKT_TYPE_VLAN_LLC_DECODE 4
++ #define RX_EV_PKT_TYPE_VLAN_JUMBO_DECODE 5
++ #define RX_EV_HDR_TYPE_LBN 42
++ #define RX_EV_HDR_TYPE_WIDTH 2
++ #define RX_EV_HDR_TYPE_TCP_IPV4_DECODE 0
++ #define RX_EV_HDR_TYPE_UDP_IPV4_DECODE 1
++ #define RX_EV_HDR_TYPE_OTHER_IP_DECODE 2
++ #define RX_EV_HDR_TYPE_NON_IP_DECODE 3
++ #define RX_EV_DESC_Q_EMPTY_LBN 41
++ #define RX_EV_DESC_Q_EMPTY_WIDTH 1
++ #define RX_EV_MCAST_HASH_MATCH_LBN 40
++ #define RX_EV_MCAST_HASH_MATCH_WIDTH 1
++ #define RX_EV_MCAST_PKT_LBN 39
++ #define RX_EV_MCAST_PKT_WIDTH 1
++ #define RX_EV_Q_LABEL_LBN 32
++ #define RX_EV_Q_LABEL_WIDTH 5
++ #define RX_JUMBO_CONT_LBN 31
++ #define RX_JUMBO_CONT_WIDTH 1
++ #define RX_SOP_LBN 15
++ #define RX_SOP_WIDTH 1
++ #define RX_PORT_LBN 30
++ #define RX_PORT_WIDTH 1
++ #define RX_EV_BYTE_CNT_LBN 16
++ #define RX_EV_BYTE_CNT_WIDTH 14
++ #define RX_iSCSI_PKT_OK_LBN 14
++ #define RX_iSCSI_PKT_OK_WIDTH 1
++ #define RX_ISCSI_DDIG_ERR_LBN 13
++ #define RX_ISCSI_DDIG_ERR_WIDTH 1
++ #define RX_ISCSI_HDIG_ERR_LBN 12
++ #define RX_ISCSI_HDIG_ERR_WIDTH 1
++ #define RX_EV_DESC_PTR_LBN 0
++ #define RX_EV_DESC_PTR_WIDTH 12
++/******---- Transmit IP events for both Kernel & User event queues ----******/
++ #define TX_EV_PKT_ERR_LBN 38
++ #define TX_EV_PKT_ERR_WIDTH 1
++ #define TX_EV_PKT_TOO_BIG_LBN 37
++ #define TX_EV_PKT_TOO_BIG_WIDTH 1
++ #define TX_EV_Q_LABEL_LBN 32
++ #define TX_EV_Q_LABEL_WIDTH 5
++ #define TX_EV_PORT_LBN 16
++ #define TX_EV_PORT_WIDTH 1
++ #define TX_EV_WQ_FF_FULL_LBN 15
++ #define TX_EV_WQ_FF_FULL_WIDTH 1
++ #define TX_EV_BUF_OWNER_ID_ERR_LBN 14
++ #define TX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++ #define TX_EV_COMP_LBN 12
++ #define TX_EV_COMP_WIDTH 1
++ #define TX_EV_DESC_PTR_LBN 0
++ #define TX_EV_DESC_PTR_WIDTH 12
++/*************---- Char or Kernel driver events ----*************/
++ #define DRIVER_EV_SUB_CODE_LBN 56
++ #define DRIVER_EV_SUB_CODE_WIDTH 4
++ #define TX_DESCQ_FLS_DONE_EV_DECODE 0x0
++ #define RX_DESCQ_FLS_DONE_EV_DECODE 0x1
++ #define EVQ_INIT_DONE_EV_DECODE 0x2
++ #define EVQ_NOT_EN_EV_DECODE 0x3
++ #define RX_DESCQ_FLSFF_OVFL_EV_DECODE 0x4
++ #define SRM_UPD_DONE_EV_DECODE 0x5
++ #define WAKE_UP_EV_DECODE 0x6
++ #define TX_PKT_NON_TCP_UDP_DECODE 0x9
++ #define TIMER_EV_DECODE 0xA
++ #define RX_DSC_ERROR_EV_DECODE 0xE
++ #define DRIVER_EV_TX_DESCQ_ID_LBN 0
++ #define DRIVER_EV_TX_DESCQ_ID_WIDTH 12
++ #define DRIVER_EV_RX_DESCQ_ID_LBN 0
++ #define DRIVER_EV_RX_DESCQ_ID_WIDTH 12
++ #define DRIVER_EV_EVQ_ID_LBN 0
++ #define DRIVER_EV_EVQ_ID_WIDTH 12
++ #define DRIVER_TMR_ID_LBN 0
++ #define DRIVER_TMR_ID_WIDTH 12
++ #define DRIVER_EV_SRM_UPD_LBN 0
++ #define DRIVER_EV_SRM_UPD_WIDTH 2
++ #define SRM_CLR_EV_DECODE 0
++ #define SRM_UPD_EV_DECODE 1
++ #define SRM_ILLCLR_EV_DECODE 2
++/********---- Global events. Sent to both event queue 0 and 4. ----********/
++ #define XFP_PHY_INTR_LBN 10
++ #define XFP_PHY_INTR_WIDTH 1
++ #define XG_PHY_INTR_LBN 9
++ #define XG_PHY_INTR_WIDTH 1
++ #define G_PHY1_INTR_LBN 8
++ #define G_PHY1_INTR_WIDTH 1
++ #define G_PHY0_INTR_LBN 7
++ #define G_PHY0_INTR_WIDTH 1
++/*************---- Driver generated events ----*************/
++ #define DRV_GEN_EV_CODE_LBN 60
++ #define DRV_GEN_EV_CODE_WIDTH 4
++ #define DRV_GEN_EV_DATA_LBN 0
++ #define DRV_GEN_EV_DATA_WIDTH 60
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_grmon.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_grmon.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_grmon.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_grmon.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,129 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) 1G MAC
++ * counters.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*************---- 1G MAC Statistical Counters C Header ----*************/
++#define GRxGoodOct_offset 0x0
++ #define GRxGoodOct_WIDTH 48
++#define GRxBadOct_offset 0x8
++ #define GRxBadOct_WIDTH 48
++#define GRxMissPkt_offset 0x10
++ #define GRxMissPkt_WIDTH 32
++#define GRxFalseCRS_offset 0x14
++ #define GRxFalseCRS_WIDTH 32
++#define GRxPausePkt_offset 0x18
++ #define GRxPausePkt_WIDTH 32
++#define GRxBadPkt_offset 0x1C
++ #define GRxBadPkt_WIDTH 32
++#define GRxUcastPkt_offset 0x20
++ #define GRxUcastPkt_WIDTH 32
++#define GRxMcastPkt_offset 0x24
++ #define GRxMcastPkt_WIDTH 32
++#define GRxBcastPkt_offset 0x28
++ #define GRxBcastPkt_WIDTH 32
++#define GRxGoodLt64Pkt_offset 0x2C
++ #define GRxGoodLt64Pkt_WIDTH 32
++#define GRxBadLt64Pkt_offset 0x30
++ #define GRxBadLt64Pkt_WIDTH 32
++#define GRx64Pkt_offset 0x34
++ #define GRx64Pkt_WIDTH 32
++#define GRx65to127Pkt_offset 0x38
++ #define GRx65to127Pkt_WIDTH 32
++#define GRx128to255Pkt_offset 0x3C
++ #define GRx128to255Pkt_WIDTH 32
++#define GRx256to511Pkt_offset 0x40
++ #define GRx256to511Pkt_WIDTH 32
++#define GRx512to1023Pkt_offset 0x44
++ #define GRx512to1023Pkt_WIDTH 32
++#define GRx1024to15xxPkt_offset 0x48
++ #define GRx1024to15xxPkt_WIDTH 32
++#define GRx15xxtoJumboPkt_offset 0x4C
++ #define GRx15xxtoJumboPkt_WIDTH 32
++#define GRxGtJumboPkt_offset 0x50
++ #define GRxGtJumboPkt_WIDTH 32
++#define GRxFcsErr64to15xxPkt_offset 0x54
++ #define GRxFcsErr64to15xxPkt_WIDTH 32
++#define GRxFcsErr15xxtoJumboPkt_offset 0x58
++ #define GRxFcsErr15xxtoJumboPkt_WIDTH 32
++#define GRxFcsErrGtJumboPkt_offset 0x5C
++ #define GRxFcsErrGtJumboPkt_WIDTH 32
++#define GTxGoodBadOct_offset 0x80
++ #define GTxGoodBadOct_WIDTH 48
++#define GTxGoodOct_offset 0x88
++ #define GTxGoodOct_WIDTH 48
++#define GTxSglColPkt_offset 0x90
++ #define GTxSglColPkt_WIDTH 32
++#define GTxMultColPkt_offset 0x94
++ #define GTxMultColPkt_WIDTH 32
++#define GTxExColPkt_offset 0x98
++ #define GTxExColPkt_WIDTH 32
++#define GTxDefPkt_offset 0x9C
++ #define GTxDefPkt_WIDTH 32
++#define GTxLateCol_offset 0xA0
++ #define GTxLateCol_WIDTH 32
++#define GTxExDefPkt_offset 0xA4
++ #define GTxExDefPkt_WIDTH 32
++#define GTxPausePkt_offset 0xA8
++ #define GTxPausePkt_WIDTH 32
++#define GTxBadPkt_offset 0xAC
++ #define GTxBadPkt_WIDTH 32
++#define GTxUcastPkt_offset 0xB0
++ #define GTxUcastPkt_WIDTH 32
++#define GTxMcastPkt_offset 0xB4
++ #define GTxMcastPkt_WIDTH 32
++#define GTxBcastPkt_offset 0xB8
++ #define GTxBcastPkt_WIDTH 32
++#define GTxLt64Pkt_offset 0xBC
++ #define GTxLt64Pkt_WIDTH 32
++#define GTx64Pkt_offset 0xC0
++ #define GTx64Pkt_WIDTH 32
++#define GTx65to127Pkt_offset 0xC4
++ #define GTx65to127Pkt_WIDTH 32
++#define GTx128to255Pkt_offset 0xC8
++ #define GTx128to255Pkt_WIDTH 32
++#define GTx256to511Pkt_offset 0xCC
++ #define GTx256to511Pkt_WIDTH 32
++#define GTx512to1023Pkt_offset 0xD0
++ #define GTx512to1023Pkt_WIDTH 32
++#define GTx1024to15xxPkt_offset 0xD4
++ #define GTx1024to15xxPkt_WIDTH 32
++#define GTx15xxtoJumboPkt_offset 0xD8
++ #define GTx15xxtoJumboPkt_WIDTH 32
++#define GTxGtJumboPkt_offset 0xDC
++ #define GTxGtJumboPkt_WIDTH 32
++#define GTxNonTcpUdpPkt_offset 0xE0
++ #define GTxNonTcpUdpPkt_WIDTH 16
++#define GTxMacSrcErrPkt_offset 0xE4
++ #define GTxMacSrcErrPkt_WIDTH 16
++#define GTxIpSrcErrPkt_offset 0xE8
++ #define GTxIpSrcErrPkt_WIDTH 16
++#define GDmaDone_offset 0xEC
++ #define GDmaDone_WIDTH 32
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,44 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) interrupt
++ * vector definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*************---- Interrupt Vector Format C Header ----*************/
++#define DW0_OFST 0x0 /* Double-word 0: Event queue FIFO interrupts */
++ #define EVQ_FIFO_HF_LBN 1
++ #define EVQ_FIFO_HF_WIDTH 1
++ #define EVQ_FIFO_AF_LBN 0
++ #define EVQ_FIFO_AF_WIDTH 1
++#define DW1_OFST 0x4 /* Double-word 1: Interrupt indicator */
++ #define INT_FLAG_LBN 0
++ #define INT_FLAG_WIDTH 1
++#define DW2_OFST 0x8 /* Double-word 2: Fatal interrupts */
++ #define FATAL_INT_LBN 0
++ #define FATAL_INT_WIDTH 1
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_mac.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_mac.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_mac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_mac.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,711 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) MAC register
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*********---- 1G/10G Ethernet MAC Wrapper Registers C Header ----*********/
++#define MD_TXD_REG_KER_OFST 0xC00 /* PHY management transmit data register */
++#define MD_TXD_REG_OFST 0xC00 /* PHY management transmit data register */
++ #define MD_TXD_LBN 0
++ #define MD_TXD_WIDTH 16
++#define MD_RXD_REG_KER_OFST 0xC10 /* PHY management receive data register */
++#define MD_RXD_REG_OFST 0xC10 /* PHY management receive data register */
++ #define MD_RXD_LBN 0
++ #define MD_RXD_WIDTH 16
++#define MD_CS_REG_KER_OFST 0xC20 /* PHY management configuration &
++ status register */
++#define MD_CS_REG_OFST 0xC20 /* PHY management configuration &
++ status register */
++ #define MD_PT_LBN 7
++ #define MD_PT_WIDTH 3
++ #define MD_PL_LBN 6
++ #define MD_PL_WIDTH 1
++ #define MD_INT_CLR_LBN 5
++ #define MD_INT_CLR_WIDTH 1
++ #define MD_GC_LBN 4
++ #define MD_GC_WIDTH 1
++ #define MD_PRSP_LBN 3
++ #define MD_PRSP_WIDTH 1
++ #define MD_RIC_LBN 2
++ #define MD_RIC_WIDTH 1
++ #define MD_RDC_LBN 1
++ #define MD_RDC_WIDTH 1
++ #define MD_WRC_LBN 0
++ #define MD_WRC_WIDTH 1
++#define MD_PHY_ADR_REG_KER_OFST 0xC30 /* PHY management PHY address register */
++#define MD_PHY_ADR_REG_OFST 0xC30 /* PHY management PHY address register */
++ #define MD_PHY_ADR_LBN 0
++ #define MD_PHY_ADR_WIDTH 16
++#define MD_ID_REG_KER_OFST 0xC40 /* PHY management ID register */
++#define MD_ID_REG_OFST 0xC40 /* PHY management ID register */
++ #define MD_PRT_ADR_LBN 11
++ #define MD_PRT_ADR_WIDTH 5
++ #define MD_DEV_ADR_LBN 6
++ #define MD_DEV_ADR_WIDTH 5
++#define MD_STAT_REG_KER_OFST 0xC50 /* PHY management status & mask register */
++#define MD_STAT_REG_OFST 0xC50 /* PHY management status & mask register */
++ #define MD_PINT_LBN 4
++ #define MD_PINT_WIDTH 1
++ #define MD_DONE_LBN 3
++ #define MD_DONE_WIDTH 1
++ #define MD_BSERR_LBN 2
++ #define MD_BSERR_WIDTH 1
++ #define MD_LNFL_LBN 1
++ #define MD_LNFL_WIDTH 1
++ #define MD_BSY_LBN 0
++ #define MD_BSY_WIDTH 1
++#define MAC0_STAT_DMA_REG_KER_OFST 0xC60 /* Port 0 MAC statistical counter
++ DMA register */
++#define MAC0_STAT_DMA_REG_OFST 0xC60 /* Port 0 MAC statistical counter
++ DMA register */
++ #define MAC0_STAT_DMA_CMD_LBN 48
++ #define MAC0_STAT_DMA_CMD_WIDTH 1
++ #define MAC0_STAT_DMA_ADR_LBN 0
++ #define MAC0_STAT_DMA_ADR_WIDTH 48
++#define MAC1_STAT_DMA_REG_KER_OFST 0xC70 /* Port 1 MAC statistical counter
++ DMA register */
++#define MAC1_STAT_DMA_REG_OFST 0xC70 /* Port 1 MAC statistical counter
++ DMA register */
++ #define MAC1_STAT_DMA_CMD_LBN 48
++ #define MAC1_STAT_DMA_CMD_WIDTH 1
++ #define MAC1_STAT_DMA_ADR_LBN 0
++ #define MAC1_STAT_DMA_ADR_WIDTH 48
++#define MAC0_CTRL_REG_KER_OFST 0xC80 /* Port 0 MAC control register */
++#define MAC0_CTRL_REG_OFST 0xC80 /* Port 0 MAC control register */
++ #define MAC0_XOFF_VAL_LBN 16
++ #define MAC0_XOFF_VAL_WIDTH 16
++ #define MAC0_BCAD_ACPT_LBN 4
++ #define MAC0_BCAD_ACPT_WIDTH 1
++ #define MAC0_UC_PROM_LBN 3
++ #define MAC0_UC_PROM_WIDTH 1
++ #define MAC0_LINK_STATUS_LBN 2
++ #define MAC0_LINK_STATUS_WIDTH 1
++ #define MAC0_SPEED_LBN 0
++ #define MAC0_SPEED_WIDTH 2
++#define MAC1_CTRL_REG_KER_OFST 0xC90 /* Port 1 MAC control register */
++#define MAC1_CTRL_REG_OFST 0xC90 /* Port 1 MAC control register */
++ #define MAC1_XOFF_VAL_LBN 16
++ #define MAC1_XOFF_VAL_WIDTH 16
++ #define MAC1_BCAD_ACPT_LBN 4
++ #define MAC1_BCAD_ACPT_WIDTH 1
++ #define MAC1_UC_PROM_LBN 3
++ #define MAC1_UC_PROM_WIDTH 1
++ #define MAC1_LINK_STATUS_LBN 2
++ #define MAC1_LINK_STATUS_WIDTH 1
++ #define MAC1_SPEED_LBN 0
++ #define MAC1_SPEED_WIDTH 2
++#define MAC_MC_HASH_REG0_KER_OFST 0xCA0 /* Multicast address hash table */
++#define MAC_MC_HASH_REG0_OFST 0xCA0 /* Multicast address hash table */
++ #define MAC_MCAST_HASH0_LBN 0
++ #define MAC_MCAST_HASH0_WIDTH 128
++#define MAC_MC_HASH_REG1_KER_OFST 0xCB0 /* Multicast address hash table */
++#define MAC_MC_HASH_REG1_OFST 0xCB0 /* Multicast address hash table */
++ #define MAC_MCAST_HASH1_LBN 0
++ #define MAC_MCAST_HASH1_WIDTH 128
++/*************---- 1G MAC Port 0 Registers C Header ----*************/
++#define GM_P0_BASE 0xE00
++#define GM_P1_BASE 0x1000
++#define GM_CFG1_REG_KER_OFST 0x00 /* GMAC configuration register 1 */
++#define GM_CFG1_REG_OFST 0x00 /* GMAC configuration register 1 */
++ #define GM_SW_RST_LBN 31
++ #define GM_SW_RST_WIDTH 1
++ #define GM_SIM_RST_LBN 30
++ #define GM_SIM_RST_WIDTH 1
++ #define GM_RST_RX_MAC_CTL_LBN 19
++ #define GM_RST_RX_MAC_CTL_WIDTH 1
++ #define GM_RST_TX_MAC_CTL_LBN 18
++ #define GM_RST_TX_MAC_CTL_WIDTH 1
++ #define GM_RST_RX_FUNC_LBN 17
++ #define GM_RST_RX_FUNC_WIDTH 1
++ #define GM_RST_TX_FUNC_LBN 16
++ #define GM_RST_TX_FUNC_WIDTH 1
++ #define GM_LOOP_LBN 8
++ #define GM_LOOP_WIDTH 1
++ #define GM_RX_FC_EN_LBN 5
++ #define GM_RX_FC_EN_WIDTH 1
++ #define GM_TX_FC_EN_LBN 4
++ #define GM_TX_FC_EN_WIDTH 1
++ #define GM_SYNC_RXEN_LBN 3
++ #define GM_SYNC_RXEN_WIDTH 1
++ #define GM_RX_EN_LBN 2
++ #define GM_RX_EN_WIDTH 1
++ #define GM_SYNC_TXEN_LBN 1
++ #define GM_SYNC_TXEN_WIDTH 1
++ #define GM_TX_EN_LBN 0
++ #define GM_TX_EN_WIDTH 1
++#define GM_CFG2_REG_KER_OFST 0x10 /* GMAC configuration register 2 */
++#define GM_CFG2_REG_OFST 0x10 /* GMAC configuration register 2 */
++ #define GM_PAMBL_LEN_LBN 12
++ #define GM_PAMBL_LEN_WIDTH 4
++ #define GM_IF_MODE_LBN 8
++ #define GM_IF_MODE_WIDTH 2
++ #define GM_HUGE_FRM_EN_LBN 5
++ #define GM_HUGE_FRM_EN_WIDTH 1
++ #define GM_LEN_CHK_LBN 4
++ #define GM_LEN_CHK_WIDTH 1
++ #define GM_PAD_CRC_EN_LBN 2
++ #define GM_PAD_CRC_EN_WIDTH 1
++ #define GM_CRC_EN_LBN 1
++ #define GM_CRC_EN_WIDTH 1
++ #define GM_FD_LBN 0
++ #define GM_FD_WIDTH 1
++#define GM_IPG_REG_KER_OFST 0x20 /* GMAC IPG register */
++#define GM_IPG_REG_OFST 0x20 /* GMAC IPG register */
++ #define GM_NONB2B_IPG1_LBN 24
++ #define GM_NONB2B_IPG1_WIDTH 7
++ #define GM_NONB2B_IPG2_LBN 16
++ #define GM_NONB2B_IPG2_WIDTH 7
++ #define GM_MIN_IPG_ENF_LBN 8
++ #define GM_MIN_IPG_ENF_WIDTH 8
++ #define GM_B2B_IPG_LBN 0
++ #define GM_B2B_IPG_WIDTH 7
++#define GM_HD_REG_KER_OFST 0x30 /* GMAC half duplex register */
++#define GM_HD_REG_OFST 0x30 /* GMAC half duplex register */
++ #define GM_ALT_BOFF_VAL_LBN 20
++ #define GM_ALT_BOFF_VAL_WIDTH 4
++ #define GM_ALT_BOFF_EN_LBN 19
++ #define GM_ALT_BOFF_EN_WIDTH 1
++ #define GM_BP_NO_BOFF_LBN 18
++ #define GM_BP_NO_BOFF_WIDTH 1
++ #define GM_DIS_BOFF_LBN 17
++ #define GM_DIS_BOFF_WIDTH 1
++ #define GM_EXDEF_TX_EN_LBN 16
++ #define GM_EXDEF_TX_EN_WIDTH 1
++ #define GM_RTRY_LIMIT_LBN 12
++ #define GM_RTRY_LIMIT_WIDTH 4
++ #define GM_COL_WIN_LBN 0
++ #define GM_COL_WIN_WIDTH 10
++#define GM_MAX_FLEN_REG_KER_OFST 0x40 /* GMAC maximum frame length register */
++#define GM_MAX_FLEN_REG_OFST 0x40 /* GMAC maximum frame length register */
++ #define GM_MAX_FLEN_LBN 0
++ #define GM_MAX_FLEN_WIDTH 16
++#define GM_TEST_REG_KER_OFST 0x70 /* GMAC test register */
++#define GM_TEST_REG_OFST 0x70 /* GMAC test register */
++ #define GM_MAX_BOFF_LBN 3
++ #define GM_MAX_BOFF_WIDTH 1
++ #define GM_REG_TX_FLOW_EN_LBN 2
++ #define GM_REG_TX_FLOW_EN_WIDTH 1
++ #define GM_TEST_PAUSE_LBN 1
++ #define GM_TEST_PAUSE_WIDTH 1
++ #define GM_SHORT_SLOT_LBN 0
++ #define GM_SHORT_SLOT_WIDTH 1
++#define GM_ADR1_REG_KER_OFST 0x100 /* GMAC station address register 1 */
++#define GM_ADR1_REG_OFST 0x100 /* GMAC station address register 1 */
++ #define GM_ADR1_LBN 0
++ #define GM_ADR1_WIDTH 32
++#define GM_ADR2_REG_KER_OFST 0x110 /* GMAC station address register 2 */
++#define GM_ADR2_REG_OFST 0x110 /* GMAC station address register 2 */
++ #define GM_ADR2_LBN 16
++ #define GM_ADR2_WIDTH 16
++#define GMF_CFG0_REG_KER_OFST 0x120 /* GMAC FIFO configuration register 0 */
++#define GMF_CFG0_REG_OFST 0x120 /* GMAC FIFO configuration register 0 */
++ #define GMF_FTFENRPLY_LBN 20
++ #define GMF_FTFENRPLY_WIDTH 1
++ #define GMF_STFENRPLY_LBN 19
++ #define GMF_STFENRPLY_WIDTH 1
++ #define GMF_FRFENRPLY_LBN 18
++ #define GMF_FRFENRPLY_WIDTH 1
++ #define GMF_SRFENRPLY_LBN 17
++ #define GMF_SRFENRPLY_WIDTH 1
++ #define GMF_WTMENRPLY_LBN 16
++ #define GMF_WTMENRPLY_WIDTH 1
++ #define GMF_FTFENREQ_LBN 12
++ #define GMF_FTFENREQ_WIDTH 1
++ #define GMF_STFENREQ_LBN 11
++ #define GMF_STFENREQ_WIDTH 1
++ #define GMF_FRFENREQ_LBN 10
++ #define GMF_FRFENREQ_WIDTH 1
++ #define GMF_SRFENREQ_LBN 9
++ #define GMF_SRFENREQ_WIDTH 1
++ #define GMF_WTMENREQ_LBN 8
++ #define GMF_WTMENREQ_WIDTH 1
++ #define GMF_HSTRSTFT_LBN 4
++ #define GMF_HSTRSTFT_WIDTH 1
++ #define GMF_HSTRSTST_LBN 3
++ #define GMF_HSTRSTST_WIDTH 1
++ #define GMF_HSTRSTFR_LBN 2
++ #define GMF_HSTRSTFR_WIDTH 1
++ #define GMF_HSTRSTSR_LBN 1
++ #define GMF_HSTRSTSR_WIDTH 1
++ #define GMF_HSTRSTWT_LBN 0
++ #define GMF_HSTRSTWT_WIDTH 1
++#define GMF_CFG1_REG_KER_OFST 0x130 /* GMAC FIFO configuration register 1 */
++#define GMF_CFG1_REG_OFST 0x130 /* GMAC FIFO configuration register 1 */
++ #define GMF_CFGFRTH_LBN 16
++ #define GMF_CFGFRTH_WIDTH 5
++ #define GMF_CFGXOFFRTX_LBN 0
++ #define GMF_CFGXOFFRTX_WIDTH 16
++#define GMF_CFG2_REG_KER_OFST 0x140 /* GMAC FIFO configuration register 2 */
++#define GMF_CFG2_REG_OFST 0x140 /* GMAC FIFO configuration register 2 */
++ #define GMF_CFGHWM_LBN 16
++ #define GMF_CFGHWM_WIDTH 6
++ #define GMF_CFGLWM_LBN 0
++ #define GMF_CFGLWM_WIDTH 6
++#define GMF_CFG3_REG_KER_OFST 0x150 /* GMAC FIFO configuration register 3 */
++#define GMF_CFG3_REG_OFST 0x150 /* GMAC FIFO configuration register 3 */
++ #define GMF_CFGHWMFT_LBN 16
++ #define GMF_CFGHWMFT_WIDTH 6
++ #define GMF_CFGFTTH_LBN 0
++ #define GMF_CFGFTTH_WIDTH 6
++#define GMF_CFG4_REG_KER_OFST 0x160 /* GMAC FIFO configuration register 4 */
++#define GMF_CFG4_REG_OFST 0x160 /* GMAC FIFO configuration register 4 */
++ #define GMF_HSTFLTRFRM_LBN 0
++ #define GMF_HSTFLTRFRM_WIDTH 18
++#define GMF_CFG5_REG_KER_OFST 0x170 /* GMAC FIFO configuration register 5 */
++#define GMF_CFG5_REG_OFST 0x170 /* GMAC FIFO configuration register 5 */
++ #define GMF_CFGHDPLX_LBN 22
++ #define GMF_CFGHDPLX_WIDTH 1
++ #define GMF_SRFULL_LBN 21
++ #define GMF_SRFULL_WIDTH 1
++ #define GMF_HSTSRFULLCLR_LBN 20
++ #define GMF_HSTSRFULLCLR_WIDTH 1
++ #define GMF_CFGBYTMODE_LBN 19
++ #define GMF_CFGBYTMODE_WIDTH 1
++ #define GMF_HSTDRPLT64_LBN 18
++ #define GMF_HSTDRPLT64_WIDTH 1
++ #define GMF_HSTFLTRFRMDC_LBN 0
++ #define GMF_HSTFLTRFRMDC_WIDTH 18
++/*************---- 10G MAC Registers C Header ----*************/
++#define XM_ADR_LO_REG_KER_P0_OFST 0x1200 /* XGMAC address register low -
++ port 0 */
++#define XM_ADR_LO_REG_P0_OFST 0x1200 /* XGMAC address register low -
++ port 0 */
++ #define XM_ADR_LO_LBN 0
++ #define XM_ADR_LO_WIDTH 32
++#define XM_ADR_HI_REG_KER_P0_OFST 0x1210 /* XGMAC address register high -
++ port 0 */
++#define XM_ADR_HI_REG_P0_OFST 0x1210 /* XGMAC address register high -
++ port 0 */
++ #define XM_ADR_HI_LBN 0
++ #define XM_ADR_HI_WIDTH 16
++#define XM_GLB_CFG_REG_KER_P0_OFST 0x1220 /* XGMAC global configuration -
++ port 0 */
++#define XM_GLB_CFG_REG_P0_OFST 0x1220 /* XGMAC global configuration -
++ port 0 */
++ #define XM_LINE_LB_DEEP_RSVD_LBN 28
++ #define XM_LINE_LB_DEEP_RSVD_WIDTH 1
++ #define XM_RMTFLT_GEN_LBN 17
++ #define XM_RMTFLT_GEN_WIDTH 1
++ #define XM_DEBUG_MODE_LBN 16
++ #define XM_DEBUG_MODE_WIDTH 1
++ #define XM_RX_STAT_EN_LBN 11
++ #define XM_RX_STAT_EN_WIDTH 1
++ #define XM_TX_STAT_EN_LBN 10
++ #define XM_TX_STAT_EN_WIDTH 1
++ #define XM_CUT_THRU_MODE_LBN 7
++ #define XM_CUT_THRU_MODE_WIDTH 1
++ #define XM_RX_JUMBO_MODE_LBN 6
++ #define XM_RX_JUMBO_MODE_WIDTH 1
++ #define XM_WAN_MODE_LBN 5
++ #define XM_WAN_MODE_WIDTH 1
++ #define XM_AUTOCLR_MODE_LBN 4
++ #define XM_AUTOCLR_MODE_WIDTH 1
++ #define XM_INTCLR_MODE_LBN 3
++ #define XM_INTCLR_MODE_WIDTH 1
++ #define XM_CORE_RST_LBN 0
++ #define XM_CORE_RST_WIDTH 1
++#define XM_TX_CFG_REG_KER_P0_OFST 0x1230 /* XGMAC transmit configuration -
++ port 0 */
++#define XM_TX_CFG_REG_P0_OFST 0x1230 /* XGMAC transmit configuration -
++ port 0 */
++ #define XM_TX_PROG_LBN 24
++ #define XM_TX_PROG_WIDTH 1
++ #define XM_IPG_LBN 16
++ #define XM_IPG_WIDTH 4
++ #define XM_FCNTL_LBN 10
++ #define XM_FCNTL_WIDTH 1
++ #define XM_TXCRC_LBN 8
++ #define XM_TXCRC_WIDTH 1
++ #define XM_EDRC_LBN 6
++ #define XM_EDRC_WIDTH 1
++ #define XM_AUTO_PAD_LBN 5
++ #define XM_AUTO_PAD_WIDTH 1
++ #define XM_TX_PRMBL_LBN 2
++ #define XM_TX_PRMBL_WIDTH 1
++ #define XM_TXEN_LBN 1
++ #define XM_TXEN_WIDTH 1
++ #define XM_TX_RST_LBN 0
++ #define XM_TX_RST_WIDTH 1
++#define XM_RX_CFG_REG_KER_P0_OFST 0x1240 /* XGMAC receive configuration -
++ port 0 */
++#define XM_RX_CFG_REG_P0_OFST 0x1240 /* XGMAC receive configuration -
++ port 0 */
++ #define XM_PASS_LENERR_LBN 26
++ #define XM_PASS_LENERR_WIDTH 1
++ #define XM_PASS_CRC_ERR_LBN 25
++ #define XM_PASS_CRC_ERR_WIDTH 1
++ #define XM_PASS_PRMBLE_ERR_LBN 24
++ #define XM_PASS_PRMBLE_ERR_WIDTH 1
++ #define XM_REJ_UCAST_LBN 18
++ #define XM_REJ_UCAST_WIDTH 1
++ #define XM_BSC_EN_LBN 17
++ #define XM_BSC_EN_WIDTH 1
++ #define XM_ACPT_ALL_MCAST_LBN 11
++ #define XM_ACPT_ALL_MCAST_WIDTH 1
++ #define XM_PASS_SAP_LBN 10
++ #define XM_PASS_SAP_WIDTH 1
++ #define XM_ACPT_ALL_UCAST_LBN 9
++ #define XM_ACPT_ALL_UCAST_WIDTH 1
++ #define XM_AUTO_DEPAD_LBN 8
++ #define XM_AUTO_DEPAD_WIDTH 1
++ #define XM_RXCRC_LBN 3
++ #define XM_RXCRC_WIDTH 1
++ #define XM_RX_PRMBL_LBN 2
++ #define XM_RX_PRMBL_WIDTH 1
++ #define XM_RXEN_LBN 1
++ #define XM_RXEN_WIDTH 1
++ #define XM_RX_RST_LBN 0
++ #define XM_RX_RST_WIDTH 1
++#define XM_FC_REG_KER_P0_OFST 0x1270 /* XGMAC flow control register -
++ port 0 */
++#define XM_FC_REG_P0_OFST 0x1270 /* XGMAC flow control register -
++ port 0 */
++ #define XM_PAUSE_TIME_LBN 16
++ #define XM_PAUSE_TIME_WIDTH 16
++ #define XM_RX_MAC_STAT_LBN 11
++ #define XM_RX_MAC_STAT_WIDTH 1
++ #define XM_TX_MAC_STAT_LBN 10
++ #define XM_TX_MAC_STAT_WIDTH 1
++ #define XM_MCNTL_PASS_LBN 8
++ #define XM_MCNTL_PASS_WIDTH 2
++ #define XM_REJ_CNTL_UCAST_LBN 6
++ #define XM_REJ_CNTL_UCAST_WIDTH 1
++ #define XM_REJ_CNTL_MCAST_LBN 5
++ #define XM_REJ_CNTL_MCAST_WIDTH 1
++ #define XM_AUTO_XMIT_ZPAUSE_LBN 4
++ #define XM_AUTO_XMIT_ZPAUSE_WIDTH 1
++ #define XM_AUTO_XMIT_PAUSE_LBN 3
++ #define XM_AUTO_XMIT_PAUSE_WIDTH 1
++ #define XM_ZPAUSE_LBN 2
++ #define XM_ZPAUSE_WIDTH 1
++ #define XM_XMIT_PAUSE_LBN 1
++ #define XM_XMIT_PAUSE_WIDTH 1
++ #define XM_DIS_FCNTL_LBN 0
++ #define XM_DIS_FCNTL_WIDTH 1
++#define XM_PAUSE_TIME_REG_KER_P0_OFST 0x1290 /* XGMAC pause time register -
++ port 0 */
++#define XM_PAUSE_TIME_REG_P0_OFST 0x1290 /* XGMAC pause time register -
++ port 0 */
++ #define XM_TX_PAUSE_CNT_LBN 16
++ #define XM_TX_PAUSE_CNT_WIDTH 16
++ #define XM_RX_PAUSE_CNT_LBN 0
++ #define XM_RX_PAUSE_CNT_WIDTH 16
++#define XM_TX_PARAM_REG_KER_P0_OFST 0x12D0 /* XGMAC transmit parameter
++ register - port 0 */
++#define XM_TX_PARAM_REG_P0_OFST 0x12D0 /* XGMAC transmit parameter register -
++ port 0 */
++ #define XM_TX_JUMBO_MODE_LBN 31
++ #define XM_TX_JUMBO_MODE_WIDTH 1
++ #define XM_MAX_TX_FRM_SIZE_LBN 16
++ #define XM_MAX_TX_FRM_SIZE_WIDTH 14
++ #define XM_PAD_CHAR_LBN 0
++ #define XM_PAD_CHAR_WIDTH 8
++#define XM_RX_PARAM_REG_KER_P0_OFST 0x12E0 /* XGMAC receive parameter
++ register - port 0 */
++#define XM_RX_PARAM_REG_P0_OFST 0x12E0 /* XGMAC receive parameter register -
++ port 0 */
++ #define XM_MAX_RX_FRM_SIZE_LBN 0
++ #define XM_MAX_RX_FRM_SIZE_WIDTH 14
++#define XX_PWR_RST_REG_KER_P0_OFST 0x1300 /* XGXS/XAUI powerdown/reset
++ register */
++#define XX_PWR_RST_REG_P0_OFST 0x1300 /* XGXS/XAUI powerdown/reset register */
++ #define XX_PWRDND_SIG_LBN 31
++ #define XX_PWRDND_SIG_WIDTH 1
++ #define XX_PWRDNC_SIG_LBN 30
++ #define XX_PWRDNC_SIG_WIDTH 1
++ #define XX_PWRDNB_SIG_LBN 29
++ #define XX_PWRDNB_SIG_WIDTH 1
++ #define XX_PWRDNA_SIG_LBN 28
++ #define XX_PWRDNA_SIG_WIDTH 1
++ #define XX_SIM_MODE_LBN 27
++ #define XX_SIM_MODE_WIDTH 1
++ #define XX_RSTPLLCD_SIG_LBN 25
++ #define XX_RSTPLLCD_SIG_WIDTH 1
++ #define XX_RSTPLLAB_SIG_LBN 24
++ #define XX_RSTPLLAB_SIG_WIDTH 1
++ #define XX_RESETD_SIG_LBN 23
++ #define XX_RESETD_SIG_WIDTH 1
++ #define XX_RESETC_SIG_LBN 22
++ #define XX_RESETC_SIG_WIDTH 1
++ #define XX_RESETB_SIG_LBN 21
++ #define XX_RESETB_SIG_WIDTH 1
++ #define XX_RESETA_SIG_LBN 20
++ #define XX_RESETA_SIG_WIDTH 1
++ #define XX_RSTXGXSTX_SIG_LBN 18
++ #define XX_RSTXGXSTX_SIG_WIDTH 1
++ #define XX_RSTXGXSRX_SIG_LBN 17
++ #define XX_RSTXGXSRX_SIG_WIDTH 1
++ #define XX_SD_RST_ACT_LBN 16
++ #define XX_SD_RST_ACT_WIDTH 1
++ #define XX_PWRDND_EN_LBN 15
++ #define XX_PWRDND_EN_WIDTH 1
++ #define XX_PWRDNC_EN_LBN 14
++ #define XX_PWRDNC_EN_WIDTH 1
++ #define XX_PWRDNB_EN_LBN 13
++ #define XX_PWRDNB_EN_WIDTH 1
++ #define XX_PWRDNA_EN_LBN 12
++ #define XX_PWRDNA_EN_WIDTH 1
++ #define XX_RSTPLLCD_EN_LBN 9
++ #define XX_RSTPLLCD_EN_WIDTH 1
++ #define XX_RSTPLLAB_EN_LBN 8
++ #define XX_RSTPLLAB_EN_WIDTH 1
++ #define XX_RESETD_EN_LBN 7
++ #define XX_RESETD_EN_WIDTH 1
++ #define XX_RESETC_EN_LBN 6
++ #define XX_RESETC_EN_WIDTH 1
++ #define XX_RESETB_EN_LBN 5
++ #define XX_RESETB_EN_WIDTH 1
++ #define XX_RESETA_EN_LBN 4
++ #define XX_RESETA_EN_WIDTH 1
++ #define XX_RSTXGXSTX_EN_LBN 2
++ #define XX_RSTXGXSTX_EN_WIDTH 1
++ #define XX_RSTXGXSRX_EN_LBN 1
++ #define XX_RSTXGXSRX_EN_WIDTH 1
++ #define XX_RST_XX_EN_LBN 0
++ #define XX_RST_XX_EN_WIDTH 1
++#define XX_SD_CTL_REG_KER_P0_OFST 0x1310 /* XGXS/XAUI powerdown/reset control
++ register */
++#define XX_SD_CTL_REG_P0_OFST 0x1310 /* XGXS/XAUI powerdown/reset control
++ register */
++ #define XX_TERMADJ1_LBN 17
++ #define XX_TERMADJ1_WIDTH 1
++ #define XX_TERMADJ0_LBN 16
++ #define XX_TERMADJ0_WIDTH 1
++ #define XX_HIDRVD_LBN 15
++ #define XX_HIDRVD_WIDTH 1
++ #define XX_LODRVD_LBN 14
++ #define XX_LODRVD_WIDTH 1
++ #define XX_HIDRVC_LBN 13
++ #define XX_HIDRVC_WIDTH 1
++ #define XX_LODRVC_LBN 12
++ #define XX_LODRVC_WIDTH 1
++ #define XX_HIDRVB_LBN 11
++ #define XX_HIDRVB_WIDTH 1
++ #define XX_LODRVB_LBN 10
++ #define XX_LODRVB_WIDTH 1
++ #define XX_HIDRVA_LBN 9
++ #define XX_HIDRVA_WIDTH 1
++ #define XX_LODRVA_LBN 8
++ #define XX_LODRVA_WIDTH 1
++ #define XX_LPBKD_LBN 3
++ #define XX_LPBKD_WIDTH 1
++ #define XX_LPBKC_LBN 2
++ #define XX_LPBKC_WIDTH 1
++ #define XX_LPBKB_LBN 1
++ #define XX_LPBKB_WIDTH 1
++ #define XX_LPBKA_LBN 0
++ #define XX_LPBKA_WIDTH 1
++#define XX_TXDRV_CTL_REG_KER_P0_OFST 0x1320 /* XAUI SerDes transmit drive
++ control register */
++#define XX_TXDRV_CTL_REG_P0_OFST 0x1320 /* XAUI SerDes transmit drive
++ control register */
++ #define XX_DEQD_LBN 28
++ #define XX_DEQD_WIDTH 4
++ #define XX_DEQC_LBN 24
++ #define XX_DEQC_WIDTH 4
++ #define XX_DEQB_LBN 20
++ #define XX_DEQB_WIDTH 4
++ #define XX_DEQA_LBN 16
++ #define XX_DEQA_WIDTH 4
++ #define XX_DTXD_LBN 12
++ #define XX_DTXD_WIDTH 4
++ #define XX_DTXC_LBN 8
++ #define XX_DTXC_WIDTH 4
++ #define XX_DTXB_LBN 4
++ #define XX_DTXB_WIDTH 4
++ #define XX_DTXA_LBN 0
++ #define XX_DTXA_WIDTH 4
++#define XX_PRBS_CTL_REG_KER_P0_OFST 0x1330 /* XAUI PRBS control register */
++#define XX_PRBS_CTL_REG_P0_OFST 0x1330 /* XAUI PRBS control register */
++ #define XX_CH3_RX_PRBS_SEL_LBN 30
++ #define XX_CH3_RX_PRBS_SEL_WIDTH 2
++ #define XX_CH3_RX_PRBS_INV_LBN 29
++ #define XX_CH3_RX_PRBS_INV_WIDTH 1
++ #define XX_CH3_RX_PRBS_CHKEN_LBN 28
++ #define XX_CH3_RX_PRBS_CHKEN_WIDTH 1
++ #define XX_CH2_RX_PRBS_SEL_LBN 26
++ #define XX_CH2_RX_PRBS_SEL_WIDTH 2
++ #define XX_CH2_RX_PRBS_INV_LBN 25
++ #define XX_CH2_RX_PRBS_INV_WIDTH 1
++ #define XX_CH2_RX_PRBS_CHKEN_LBN 24
++ #define XX_CH2_RX_PRBS_CHKEN_WIDTH 1
++ #define XX_CH1_RX_PRBS_SEL_LBN 22
++ #define XX_CH1_RX_PRBS_SEL_WIDTH 2
++ #define XX_CH1_RX_PRBS_INV_LBN 21
++ #define XX_CH1_RX_PRBS_INV_WIDTH 1
++ #define XX_CH1_RX_PRBS_CHKEN_LBN 20
++ #define XX_CH1_RX_PRBS_CHKEN_WIDTH 1
++ #define XX_CH0_RX_PRBS_SEL_LBN 18
++ #define XX_CH0_RX_PRBS_SEL_WIDTH 2
++ #define XX_CH0_RX_PRBS_INV_LBN 17
++ #define XX_CH0_RX_PRBS_INV_WIDTH 1
++ #define XX_CH0_RX_PRBS_CHKEN_LBN 16
++ #define XX_CH0_RX_PRBS_CHKEN_WIDTH 1
++ #define XX_CH3_TX_PRBS_SEL_LBN 14
++ #define XX_CH3_TX_PRBS_SEL_WIDTH 2
++ #define XX_CH3_TX_PRBS_INV_LBN 13
++ #define XX_CH3_TX_PRBS_INV_WIDTH 1
++ #define XX_CH3_TX_PRBS_CHKEN_LBN 12
++ #define XX_CH3_TX_PRBS_CHKEN_WIDTH 1
++ #define XX_CH2_TX_PRBS_SEL_LBN 10
++ #define XX_CH2_TX_PRBS_SEL_WIDTH 2
++ #define XX_CH2_TX_PRBS_INV_LBN 9
++ #define XX_CH2_TX_PRBS_INV_WIDTH 1
++ #define XX_CH2_TX_PRBS_CHKEN_LBN 8
++ #define XX_CH2_TX_PRBS_CHKEN_WIDTH 1
++ #define XX_CH1_TX_PRBS_SEL_LBN 6
++ #define XX_CH1_TX_PRBS_SEL_WIDTH 2
++ #define XX_CH1_TX_PRBS_INV_LBN 5
++ #define XX_CH1_TX_PRBS_INV_WIDTH 1
++ #define XX_CH1_TX_PRBS_CHKEN_LBN 4
++ #define XX_CH1_TX_PRBS_CHKEN_WIDTH 1
++ #define XX_CH0_TX_PRBS_SEL_LBN 2
++ #define XX_CH0_TX_PRBS_SEL_WIDTH 2
++ #define XX_CH0_TX_PRBS_INV_LBN 1
++ #define XX_CH0_TX_PRBS_INV_WIDTH 1
++ #define XX_CH0_TX_PRBS_CHKEN_LBN 0
++ #define XX_CH0_TX_PRBS_CHKEN_WIDTH 1
++#define XX_PRBS_CHK_REG_KER_P0_OFST 0x1340 /* XAUI PRBS checker control
++ register */
++#define XX_PRBS_CHK_REG_P0_OFST 0x1340 /* XAUI PRBS checker control
++ register */
++ #define XX_REV_LB_EN_LBN 16
++ #define XX_REV_LB_EN_WIDTH 1
++ #define XX_CH3_DEG_DET_LBN 15
++ #define XX_CH3_DEG_DET_WIDTH 1
++ #define XX_CH3_LFSR_LOCK_IND_LBN 14
++ #define XX_CH3_LFSR_LOCK_IND_WIDTH 1
++ #define XX_CH3_PRBS_FRUN_LBN 13
++ #define XX_CH3_PRBS_FRUN_WIDTH 1
++ #define XX_CH3_ERR_CHK_LBN 12
++ #define XX_CH3_ERR_CHK_WIDTH 1
++ #define XX_CH2_DEG_DET_LBN 11
++ #define XX_CH2_DEG_DET_WIDTH 1
++ #define XX_CH2_LFSR_LOCK_IND_LBN 10
++ #define XX_CH2_LFSR_LOCK_IND_WIDTH 1
++ #define XX_CH2_PRBS_FRUN_LBN 9
++ #define XX_CH2_PRBS_FRUN_WIDTH 1
++ #define XX_CH2_ERR_CHK_LBN 8
++ #define XX_CH2_ERR_CHK_WIDTH 1
++ #define XX_CH1_DEG_DET_LBN 7
++ #define XX_CH1_DEG_DET_WIDTH 1
++ #define XX_CH1_LFSR_LOCK_IND_LBN 6
++ #define XX_CH1_LFSR_LOCK_IND_WIDTH 1
++ #define XX_CH1_PRBS_FRUN_LBN 5
++ #define XX_CH1_PRBS_FRUN_WIDTH 1
++ #define XX_CH1_ERR_CHK_LBN 4
++ #define XX_CH1_ERR_CHK_WIDTH 1
++ #define XX_CH0_DEG_DET_LBN 3
++ #define XX_CH0_DEG_DET_WIDTH 1
++ #define XX_CH0_LFSR_LOCK_IND_LBN 2
++ #define XX_CH0_LFSR_LOCK_IND_WIDTH 1
++ #define XX_CH0_PRBS_FRUN_LBN 1
++ #define XX_CH0_PRBS_FRUN_WIDTH 1
++ #define XX_CH0_ERR_CHK_LBN 0
++ #define XX_CH0_ERR_CHK_WIDTH 1
++#define XX_PRBS_ERR_REG_KER_P0_OFST 0x1350 /* XAUI PRBS checker error
++ count register */
++#define XX_PRBS_ERR_REG_P0_OFST 0x1350 /* XAUI PRBS checker error count
++ register */
++ #define XX_CH3_PRBS_ERR_CNT_LBN 24
++ #define XX_CH3_PRBS_ERR_CNT_WIDTH 8
++ #define XX_CH2_PRBS_ERR_CNT_LBN 16
++ #define XX_CH2_PRBS_ERR_CNT_WIDTH 8
++ #define XX_CH1_PRBS_ERR_CNT_LBN 8
++ #define XX_CH1_PRBS_ERR_CNT_WIDTH 8
++ #define XX_CH0_PRBS_ERR_CNT_LBN 0
++ #define XX_CH0_PRBS_ERR_CNT_WIDTH 8
++#define XX_CORE_STAT_REG_KER_P0_OFST 0x1360 /* XAUI XGXS core status
++ register */
++#define XX_CORE_STAT_REG_P0_OFST 0x1360 /* XAUI XGXS core status register */
++ #define XX_FORCE_SIG3_LBN 31
++ #define XX_FORCE_SIG3_WIDTH 1
++ #define XX_FORCE_SIG3_VAL_LBN 30
++ #define XX_FORCE_SIG3_VAL_WIDTH 1
++ #define XX_FORCE_SIG2_LBN 29
++ #define XX_FORCE_SIG2_WIDTH 1
++ #define XX_FORCE_SIG2_VAL_LBN 28
++ #define XX_FORCE_SIG2_VAL_WIDTH 1
++ #define XX_FORCE_SIG1_LBN 27
++ #define XX_FORCE_SIG1_WIDTH 1
++ #define XX_FORCE_SIG1_VAL_LBN 26
++ #define XX_FORCE_SIG1_VAL_WIDTH 1
++ #define XX_FORCE_SIG0_LBN 25
++ #define XX_FORCE_SIG0_WIDTH 1
++ #define XX_FORCE_SIG0_VAL_LBN 24
++ #define XX_FORCE_SIG0_VAL_WIDTH 1
++ #define XX_XGXS_LB_EN_LBN 23
++ #define XX_XGXS_LB_EN_WIDTH 1
++ #define XX_XGMII_LB_EN_LBN 22
++ #define XX_XGMII_LB_EN_WIDTH 1
++ #define XX_MATCH_FAULT_LBN 21
++ #define XX_MATCH_FAULT_WIDTH 1
++ #define XX_ALIGN_DONE_LBN 20
++ #define XX_ALIGN_DONE_WIDTH 1
++ #define XX_SYNC_STAT3_LBN 19
++ #define XX_SYNC_STAT3_WIDTH 1
++ #define XX_SYNC_STAT2_LBN 18
++ #define XX_SYNC_STAT2_WIDTH 1
++ #define XX_SYNC_STAT1_LBN 17
++ #define XX_SYNC_STAT1_WIDTH 1
++ #define XX_SYNC_STAT0_LBN 16
++ #define XX_SYNC_STAT0_WIDTH 1
++ #define XX_COMMA_DET_CH3_LBN 15
++ #define XX_COMMA_DET_CH3_WIDTH 1
++ #define XX_COMMA_DET_CH2_LBN 14
++ #define XX_COMMA_DET_CH2_WIDTH 1
++ #define XX_COMMA_DET_CH1_LBN 13
++ #define XX_COMMA_DET_CH1_WIDTH 1
++ #define XX_COMMA_DET_CH0_LBN 12
++ #define XX_COMMA_DET_CH0_WIDTH 1
++ #define XX_CGRP_ALIGN_CH3_LBN 11
++ #define XX_CGRP_ALIGN_CH3_WIDTH 1
++ #define XX_CGRP_ALIGN_CH2_LBN 10
++ #define XX_CGRP_ALIGN_CH2_WIDTH 1
++ #define XX_CGRP_ALIGN_CH1_LBN 9
++ #define XX_CGRP_ALIGN_CH1_WIDTH 1
++ #define XX_CGRP_ALIGN_CH0_LBN 8
++ #define XX_CGRP_ALIGN_CH0_WIDTH 1
++ #define XX_CHAR_ERR_CH3_LBN 7
++ #define XX_CHAR_ERR_CH3_WIDTH 1
++ #define XX_CHAR_ERR_CH2_LBN 6
++ #define XX_CHAR_ERR_CH2_WIDTH 1
++ #define XX_CHAR_ERR_CH1_LBN 5
++ #define XX_CHAR_ERR_CH1_WIDTH 1
++ #define XX_CHAR_ERR_CH0_LBN 4
++ #define XX_CHAR_ERR_CH0_WIDTH 1
++ #define XX_DISPERR_CH3_LBN 3
++ #define XX_DISPERR_CH3_WIDTH 1
++ #define XX_DISPERR_CH2_LBN 2
++ #define XX_DISPERR_CH2_WIDTH 1
++ #define XX_DISPERR_CH1_LBN 1
++ #define XX_DISPERR_CH1_WIDTH 1
++ #define XX_DISPERR_CH0_LBN 0
++ #define XX_DISPERR_CH0_WIDTH 1
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_xgrmon.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_xgrmon.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_xgrmon.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_xgrmon.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,125 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) 10G MAC
++ * statistics register definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*************---- 10G MAC Statistical Counters C Header ----*************/
++#define XgRxOctets_offset 0x0
++ #define XgRxOctets_WIDTH 48
++#define XgRxOctetsOK_offset 0x8
++ #define XgRxOctetsOK_WIDTH 48
++#define XgRxPkts_offset 0x10
++ #define XgRxPkts_WIDTH 32
++#define XgRxPktsOK_offset 0x14
++ #define XgRxPktsOK_WIDTH 32
++#define XgRxBroadcastPkts_offset 0x18
++ #define XgRxBroadcastPkts_WIDTH 32
++#define XgRxMulticastPkts_offset 0x1C
++ #define XgRxMulticastPkts_WIDTH 32
++#define XgRxUnicastPkts_offset 0x20
++ #define XgRxUnicastPkts_WIDTH 32
++#define XgRxUndersizePkts_offset 0x24
++ #define XgRxUndersizePkts_WIDTH 32
++#define XgRxOversizePkts_offset 0x28
++ #define XgRxOversizePkts_WIDTH 32
++#define XgRxJabberPkts_offset 0x2C
++ #define XgRxJabberPkts_WIDTH 32
++#define XgRxUndersizeFCSerrorPkts_offset 0x30
++ #define XgRxUndersizeFCSerrorPkts_WIDTH 32
++#define XgRxDropEvents_offset 0x34
++ #define XgRxDropEvents_WIDTH 32
++#define XgRxFCSerrorPkts_offset 0x38
++ #define XgRxFCSerrorPkts_WIDTH 32
++#define XgRxAlignError_offset 0x3C
++ #define XgRxAlignError_WIDTH 32
++#define XgRxSymbolError_offset 0x40
++ #define XgRxSymbolError_WIDTH 32
++#define XgRxInternalMACError_offset 0x44
++ #define XgRxInternalMACError_WIDTH 32
++#define XgRxControlPkts_offset 0x48
++ #define XgRxControlPkts_WIDTH 32
++#define XgRxPausePkts_offset 0x4C
++ #define XgRxPausePkts_WIDTH 32
++#define XgRxPkts64Octets_offset 0x50
++ #define XgRxPkts64Octets_WIDTH 32
++#define XgRxPkts65to127Octets_offset 0x54
++ #define XgRxPkts65to127Octets_WIDTH 32
++#define XgRxPkts128to255Octets_offset 0x58
++ #define XgRxPkts128to255Octets_WIDTH 32
++#define XgRxPkts256to511Octets_offset 0x5C
++ #define XgRxPkts256to511Octets_WIDTH 32
++#define XgRxPkts512to1023Octets_offset 0x60
++ #define XgRxPkts512to1023Octets_WIDTH 32
++#define XgRxPkts1024to15xxOctets_offset 0x64
++ #define XgRxPkts1024to15xxOctets_WIDTH 32
++#define XgRxPkts15xxtoMaxOctets_offset 0x68
++ #define XgRxPkts15xxtoMaxOctets_WIDTH 32
++#define XgRxLengthError_offset 0x6C
++ #define XgRxLengthError_WIDTH 32
++#define XgTxPkts_offset 0x80
++ #define XgTxPkts_WIDTH 32
++#define XgTxOctets_offset 0x88
++ #define XgTxOctets_WIDTH 48
++#define XgTxMulticastPkts_offset 0x90
++ #define XgTxMulticastPkts_WIDTH 32
++#define XgTxBroadcastPkts_offset 0x94
++ #define XgTxBroadcastPkts_WIDTH 32
++#define XgTxUnicastPkts_offset 0x98
++ #define XgTxUnicastPkts_WIDTH 32
++#define XgTxControlPkts_offset 0x9C
++ #define XgTxControlPkts_WIDTH 32
++#define XgTxPausePkts_offset 0xA0
++ #define XgTxPausePkts_WIDTH 32
++#define XgTxPkts64Octets_offset 0xA4
++ #define XgTxPkts64Octets_WIDTH 32
++#define XgTxPkts65to127Octets_offset 0xA8
++ #define XgTxPkts65to127Octets_WIDTH 32
++#define XgTxPkts128to255Octets_offset 0xAC
++ #define XgTxPkts128to255Octets_WIDTH 32
++#define XgTxPkts256to511Octets_offset 0xB0
++ #define XgTxPkts256to511Octets_WIDTH 32
++#define XgTxPkts512to1023Octets_offset 0xB4
++ #define XgTxPkts512to1023Octets_WIDTH 32
++#define XgTxPkts1024to15xxOctets_offset 0xB8
++ #define XgTxPkts1024to15xxOctets_WIDTH 32
++#define XgTxPkts1519toMaxOctets_offset 0xBC
++ #define XgTxPkts1519toMaxOctets_WIDTH 32
++#define XgTxUndersizePkts_offset 0xC0
++ #define XgTxUndersizePkts_WIDTH 32
++#define XgTxOversizePkts_offset 0xC4
++ #define XgTxOversizePkts_WIDTH 32
++#define xGTxNonTcpUdpPkt_offset 0xC8
++ #define xGTxNonTcpUdpPkt_WIDTH 16
++#define xGTxMacSrcErrPkt_offset 0xCC
++ #define xGTxMacSrcErrPkt_WIDTH 16
++#define xGTxIpSrcErrPkt_offset 0xD0
++ #define xGTxIpSrcErrPkt_WIDTH 16
++#define XgDmaDone_offset 0xD4
++ #define XgDmaDone_WIDTH 32
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,420 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) specific
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_HARDWARE_FALCON_H__
++#define __CI_DRIVER_EFAB_HARDWARE_FALCON_H__
++
++/*----------------------------------------------------------------------------
++ * Compile options
++ *---------------------------------------------------------------------------*/
++
++/* Falcon has an 8K maximum page size. */
++#define FALCON_MAX_PAGE_SIZE EFHW_8K
++
++/* include the register definitions */
++#include <ci/driver/efab/hardware/falcon/falcon_core.h>
++#include <ci/driver/efab/hardware/falcon/falcon_desc.h>
++#include <ci/driver/efab/hardware/falcon/falcon_event.h>
++#include <ci/driver/efab/hardware/falcon/falcon_mac.h>
++#include <ci/driver/efab/hardware/falcon/falcon_grmon.h>
++#include <ci/driver/efab/hardware/falcon/falcon_xgrmon.h>
++#include <ci/driver/efab/hardware/falcon/falcon_intr_vec.h>
++
++#define FALCON_DMA_TX_DESC_BYTES 8
++#define FALCON_DMA_RX_PHYS_DESC_BYTES 8
++#define FALCON_DMA_RX_BUF_DESC_BYTES 4
++
++
++/* ---- efhw_event_t helpers --- */
++
++#ifndef EFHW_IS_LITTLE_ENDIAN
++#error This needs lots of cpu_to_le64s() in
++#endif
++
++/*!\ TODO look at whether there is an efficiency gain to be had by
++ treating the event codes to 32bit masks as is done for EF1
++
++ These masks apply to the full 64 bits of the event to extract the
++ event code - followed by the common event codes to expect
++ */
++#define __FALCON_OPEN_MASK(WIDTH) ((((uint64_t)1) << (WIDTH)) - 1)
++#define FALCON_EVENT_CODE_MASK \
++ (__FALCON_OPEN_MASK(EV_CODE_WIDTH) << EV_CODE_LBN)
++#define FALCON_EVENT_EV_Q_ID_MASK \
++ (__FALCON_OPEN_MASK(DRIVER_EV_EVQ_ID_WIDTH) << DRIVER_EV_EVQ_ID_LBN)
++#define FALCON_EVENT_TX_FLUSH_Q_ID_MASK \
++ (__FALCON_OPEN_MASK(DRIVER_EV_TX_DESCQ_ID_WIDTH) << \
++ DRIVER_EV_TX_DESCQ_ID_LBN)
++#define FALCON_EVENT_RX_FLUSH_Q_ID_MASK \
++ (__FALCON_OPEN_MASK(DRIVER_EV_RX_DESCQ_ID_WIDTH) << \
++ DRIVER_EV_RX_DESCQ_ID_LBN)
++#define FALCON_EVENT_DRV_SUBCODE_MASK \
++ (__FALCON_OPEN_MASK(DRIVER_EV_SUB_CODE_WIDTH) << \
++ DRIVER_EV_SUB_CODE_LBN)
++
++#define FALCON_EVENT_FMT "[ev:%x:%08x:%08x]"
++#define FALCON_EVENT_PRI_ARG(e) \
++ ((unsigned)(((e).u64 & FALCON_EVENT_CODE_MASK) >> EV_CODE_LBN)), \
++ ((unsigned)((e).u64 >> 32)), ((unsigned)((e).u64 & 0xFFFFFFFF))
++
++#define FALCON_EVENT_CODE(evp) ((evp)->u64 & FALCON_EVENT_CODE_MASK)
++#define FALCON_EVENT_WAKE_EVQ_ID(evp) \
++ (((evp)->u64 & FALCON_EVENT_EV_Q_ID_MASK) >> DRIVER_EV_EVQ_ID_LBN)
++#define FALCON_EVENT_TX_FLUSH_Q_ID(evp) \
++ (((evp)->u64 & FALCON_EVENT_TX_FLUSH_Q_ID_MASK) >> \
++ DRIVER_EV_TX_DESCQ_ID_LBN)
++#define FALCON_EVENT_RX_FLUSH_Q_ID(evp) \
++ (((evp)->u64 & FALCON_EVENT_RX_FLUSH_Q_ID_MASK) >> \
++ DRIVER_EV_RX_DESCQ_ID_LBN)
++#define FALCON_EVENT_DRIVER_SUBCODE(evp) \
++ (((evp)->u64 & FALCON_EVENT_DRV_SUBCODE_MASK) >> \
++ DRIVER_EV_SUB_CODE_LBN)
++
++#define FALCON_EVENT_CODE_CHAR ((uint64_t)DRIVER_EV_DECODE << EV_CODE_LBN)
++#define FALCON_EVENT_CODE_SW ((uint64_t)DRV_GEN_EV_DECODE << EV_CODE_LBN)
++
++
++/* so this is the size in bytes of an awful lot of things */
++#define FALCON_REGISTER128 (16)
++
++/* we define some unique dummy values as a debug aid */
++#ifdef _WIN32
++#define FALCON_ATOMIC_BASE 0xdeadbeef00000000ui64
++#else
++#define FALCON_ATOMIC_BASE 0xdeadbeef00000000ULL
++#endif
++#define FALCON_ATOMIC_UPD_REG (FALCON_ATOMIC_BASE | 0x1)
++#define FALCON_ATOMIC_PTR_TBL_REG (FALCON_ATOMIC_BASE | 0x2)
++#define FALCON_ATOMIC_SRPM_UDP_EVQ_REG (FALCON_ATOMIC_BASE | 0x3)
++#define FALCON_ATOMIC_RX_FLUSH_DESCQ (FALCON_ATOMIC_BASE | 0x4)
++#define FALCON_ATOMIC_TX_FLUSH_DESCQ (FALCON_ATOMIC_BASE | 0x5)
++#define FALCON_ATOMIC_INT_EN_REG (FALCON_ATOMIC_BASE | 0x6)
++#define FALCON_ATOMIC_TIMER_CMD_REG (FALCON_ATOMIC_BASE | 0x7)
++#define FALCON_ATOMIC_PACE_REG (FALCON_ATOMIC_BASE | 0x8)
++#define FALCON_ATOMIC_INT_ACK_REG (FALCON_ATOMIC_BASE | 0x9)
++/* XXX It crashed with odd value in FALCON_ATOMIC_INT_ADR_REG */
++#define FALCON_ATOMIC_INT_ADR_REG (FALCON_ATOMIC_BASE | 0xa)
++
++/*----------------------------------------------------------------------------
++ *
++ * PCI control blocks for Falcon -
++ * (P) primary is for NET
++ * (S) secondary is for CHAR
++ *
++ *---------------------------------------------------------------------------*/
++
++#define FALCON_P_CTR_AP_BAR 2
++#define FALCON_S_CTR_AP_BAR 0
++#define FALCON_S_DEVID 0x6703
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Falcon constants
++ *
++ *---------------------------------------------------------------------------*/
++
++#define FALCON_DMAQ_NUM (EFHW_4K)
++#define FALCON_EVQ_TBL_NUM (EFHW_4K)
++#define FALCON_TIMERS_NUM (EFHW_4K)
++
++/* This value is an upper limit on the total number of filter table
++ * entries, including odd and even banks. The actual size of filter table
++ * is determined at runtime, as it can vary.
++ */
++#define FALCON_FILTER_TBL_NUM (EFHW_16K)
++
++/* max number of buffers which can be pushed before commiting */
++#define FALCON_BUFFER_UPD_MAX (128)
++
++/* We can tell falcon to write its RX buffers in 32 byte quantums,
++ and since we pad packets 2 bytes to the right we can't use
++ a full page (not unless we use jumbo mode for all queues)
++
++ NOTE: tests/nic/dma.c assumes that the value here is the real NIC
++ value, so we explicitly round it down to the nearest 32 bytes */
++
++/* #define FALCON_RX_USR_BUF_SIZE round_down(4096-2,32) */
++#define FALCON_RX_USR_BUF_SIZE 4064
++
++#define FALCON_EVQ_RPTR_REG_P0 0x400
++
++/*----------------------------------------------------------------------------
++ *
++ * Falcon requires user-space descriptor pushes to be:
++ * dword[0-2]; wiob(); dword[3]
++ *
++ * Driver register access must be locked against other threads from
++ * the same driver but can be in any order: i.e dword[0-3]; wiob()
++ *
++ * The following helpers ensure that valid dword orderings are exercised
++ *
++ *---------------------------------------------------------------------------*/
++
++/* A union to allow writting 64bit values as 32bit values, without
++ * hitting the compilers aliasing rules. We hope the compiler optimises
++ * away the copy's anyway */
++union __u64to32 {
++ uint64_t u64;
++ struct {
++#ifdef EFHW_IS_LITTLE_ENDIAN
++ uint32_t a;
++ uint32_t b;
++#else
++ uint32_t b;
++ uint32_t a;
++#endif
++ } s;
++};
++
++static inline void
++falcon_write_ddd_d(efhw_ioaddr_t kva,
++ uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3)
++{
++ writel(d0, kva + 0);
++ writel(d1, kva + 4);
++ writel(d2, kva + 8);
++ mmiowb();
++ writel(d3, kva + 12);
++}
++
++static inline void falcon_write_q(efhw_ioaddr_t kva, uint64_t q)
++{
++ union __u64to32 u;
++ u.u64 = q;
++
++ writel(u.s.a, kva);
++ mmiowb();
++ writel(u.s.b, kva + 4);
++}
++
++static inline void falcon_read_q(efhw_ioaddr_t addr, uint64_t *q0)
++{
++ /* It is essential that we read dword0 first, so that
++ * the shadow register is updated with the latest value
++ * and we get a self consistent value.
++ */
++ union __u64to32 u;
++ u.s.a = readl(addr);
++ rmb();
++ u.s.b = readl(addr + 4);
++
++ *q0 = u.u64;
++}
++
++static inline void
++falcon_write_qq(efhw_ioaddr_t kva, uint64_t q0, uint64_t q1)
++{
++ writeq(q0, kva + 0);
++ falcon_write_q(kva + 8, q1);
++}
++
++static inline void
++falcon_read_qq(efhw_ioaddr_t addr, uint64_t *q0, uint64_t *q1)
++{
++ falcon_read_q(addr, q0);
++ *q1 = readq(addr + 8);
++}
++
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Buffer virtual addresses (4K buffers)
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Form a buffer virtual address from buffer ID and offset. If the offset
++** is larger than the buffer size, then the buffer indexed will be
++** calculated appropriately. It is the responsibility of the caller to
++** ensure that they have valid buffers programmed at that address.
++*/
++#define FALCON_VADDR_8K_S (13)
++#define FALCON_VADDR_4K_S (12)
++#define FALCON_VADDR_M 0xfffff /* post shift mask */
++
++#define FALCON_BUFFER_8K_ADDR(id, off) (((id) << FALCON_VADDR_8K_S) + (off))
++#define FALCON_BUFFER_8K_PAGE(vaddr) \
++ (((vaddr) >> FALCON_VADDR_8K_S) & FALCON_VADDR_M)
++#define FALCON_BUFFER_8K_OFF(vaddr) \
++ ((vaddr) & __FALCON_MASK32(FALCON_VADDR_8K_S))
++
++#define FALCON_BUFFER_4K_ADDR(id, off) (((id) << FALCON_VADDR_4K_S) + (off))
++#define FALCON_BUFFER_4K_PAGE(vaddr) \
++ (((vaddr) >> FALCON_VADDR_4K_S) & FALCON_VADDR_M)
++#define FALCON_BUFFER_4K_OFF(vaddr) \
++ ((vaddr) & __FALCON_MASK32(FALCON_VADDR_4K_S))
++
++/*----------------------------------------------------------------------------
++ *
++ * Timer helpers
++ *
++ *---------------------------------------------------------------------------*/
++
++static inline int falcon_timer_page_addr(uint idx)
++{
++
++ EFHW_ASSERT(TIMER_CMD_REG_KER_OFST ==
++ (TIMER_CMD_REG_PAGE4_OFST - 4 * EFHW_8K));
++
++ EFHW_ASSERT(idx < FALCON_TIMERS_NUM);
++
++ if (idx < 4)
++ return TIMER_CMD_REG_KER_OFST + (idx * EFHW_8K);
++ else if (idx < 1024)
++ return TIMER_CMD_REG_PAGE4_OFST + ((idx - 4) * EFHW_8K);
++ else
++ return TIMER_CMD_REG_PAGE123K_OFST + ((idx - 1024) * EFHW_8K);
++}
++
++#define FALCON_TIMER_PAGE_MASK (EFHW_8K-1)
++
++static inline int falcon_timer_page_offset(uint idx)
++{
++ return falcon_timer_page_addr(idx) & FALCON_TIMER_PAGE_MASK;
++}
++
++/*----------------------------------------------------------------------------
++ *
++ * DMA Queue helpers
++ *
++ *---------------------------------------------------------------------------*/
++
++/* iSCSI queue for A1; see bug 5427 for more details. */
++#define FALCON_A1_ISCSI_DMAQ 4
++
++/*! returns an address within a bar of the TX DMA doorbell */
++static inline uint falcon_tx_dma_page_addr(uint dmaq_idx)
++{
++ uint page;
++
++ EFHW_ASSERT((((TX_DESC_UPD_REG_PAGE123K_OFST) & (EFHW_8K - 1)) ==
++ (((TX_DESC_UPD_REG_PAGE4_OFST) & (EFHW_8K - 1)))));
++
++ EFHW_ASSERT(dmaq_idx < FALCON_DMAQ_NUM);
++
++ if (dmaq_idx < 1024)
++ page = TX_DESC_UPD_REG_PAGE4_OFST + ((dmaq_idx - 4) * EFHW_8K);
++ else
++ page =
++ TX_DESC_UPD_REG_PAGE123K_OFST +
++ ((dmaq_idx - 1024) * EFHW_8K);
++
++ return page;
++}
++
++/*! returns an address within a bar of the RX DMA doorbell */
++static inline uint falcon_rx_dma_page_addr(uint dmaq_idx)
++{
++ uint page;
++
++ EFHW_ASSERT((((RX_DESC_UPD_REG_PAGE123K_OFST) & (EFHW_8K - 1)) ==
++ ((RX_DESC_UPD_REG_PAGE4_OFST) & (EFHW_8K - 1))));
++
++ EFHW_ASSERT(dmaq_idx < FALCON_DMAQ_NUM);
++
++ if (dmaq_idx < 1024)
++ page = RX_DESC_UPD_REG_PAGE4_OFST + ((dmaq_idx - 4) * EFHW_8K);
++ else
++ page =
++ RX_DESC_UPD_REG_PAGE123K_OFST +
++ ((dmaq_idx - 1024) * EFHW_8K);
++
++ return page;
++}
++
++/*! "page"=NIC-dependent register set size */
++#define FALCON_DMA_PAGE_MASK (EFHW_8K-1)
++
++/*! returns an address within a bar of the start of the "page"
++ containing the TX DMA doorbell */
++static inline int falcon_tx_dma_page_base(uint dma_idx)
++{
++ return falcon_tx_dma_page_addr(dma_idx) & ~FALCON_DMA_PAGE_MASK;
++}
++
++/*! returns an address within a bar of the start of the "page"
++ containing the RX DMA doorbell */
++static inline int falcon_rx_dma_page_base(uint dma_idx)
++{
++ return falcon_rx_dma_page_addr(dma_idx) & ~FALCON_DMA_PAGE_MASK;
++}
++
++/*! returns an offset within a "page" of the TX DMA doorbell */
++static inline int falcon_tx_dma_page_offset(uint dma_idx)
++{
++ return falcon_tx_dma_page_addr(dma_idx) & FALCON_DMA_PAGE_MASK;
++}
++
++/*! returns an offset within a "page" of the RX DMA doorbell */
++static inline int falcon_rx_dma_page_offset(uint dma_idx)
++{
++ return falcon_rx_dma_page_addr(dma_idx) & FALCON_DMA_PAGE_MASK;
++}
++
++/*----------------------------------------------------------------------------
++ *
++ * Events
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Falcon nails down the event queue mappings */
++#define FALCON_EVQ_KERNEL0 (0) /* hardwired for net driver */
++#define FALCON_EVQ_CHAR (4) /* char driver's event queue */
++#define FALCON_EVQ_NONIRQ (5) /* char driver's non interrupting
++ queue. Subsequent queues are
++ available for user apps */
++
++/* reserved by the drivers */
++#define FALCON_EVQ_TBL_RESERVED (8)
++
++/* default DMA-Q sizes */
++#define FALCON_DMA_Q_DEFAULT_TX_SIZE 512
++
++#define FALCON_DMA_Q_DEFAULT_RX_SIZE 512
++
++#define FALCON_DMA_Q_DEFAULT_MMAP \
++ (FALCON_DMA_Q_DEFAULT_TX_SIZE * (FALCON_DMA_TX_DESC_BYTES * 2))
++
++/*----------------------------------------------------------------------------
++ *
++ * DEBUG - Analyser trigger
++ *
++ *---------------------------------------------------------------------------*/
++
++static inline void falcon_deadbeef(efhw_ioaddr_t efhw_kva, unsigned what)
++{
++ writel(what, efhw_kva + 0x300);
++ mmiowb();
++}
++#endif /* __CI_DRIVER_EFAB_HARDWARE_FALCON_H__ */
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,75 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides workaround settings for EtherFabric NICs.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_WORKAROUNDS_H__
++#define __CI_DRIVER_EFAB_WORKAROUNDS_H__
++
++/*----------------------------------------------------------------------------
++ *
++ * Hardware workarounds which have global scope
++ *
++ *---------------------------------------------------------------------------*/
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON_B0__)
++/*------------------------------- B0 ---------------------------------------*/
++
++#define BUG2175_WORKAROUND 0 /* TX event batching for dual port operation.
++ This removes the effect (dup TX events)
++ of the fix
++ (TX event per packet + batch events) */
++#define BUG5302_WORKAROUND 0 /* unstick TX DMAQ after out-of-range wr ptr */
++#define BUG5475_WORKAROUND 1 /* 10G SNAP encapsulation broken */
++#define BUG5762_WORKAROUND 0 /* Set all queues to jumbo mode */
++#define BUG5391_WORKAROUND 0 /* Misaligned TX can't span 512-byte boundary */
++#define BUG7916_WORKAROUND 0 /* RX flush gets lost */
++
++#else
++/*------------------------------- A0/A1 ------------------------------------*/
++
++#define BUG2175_WORKAROUND 1 /* TX event batching for dual port operation.
++ This removes the effect (dup TX events)
++ of the fix
++ (TX event per packet + batch events) */
++#define BUG5302_WORKAROUND 1 /* unstick TX DMAQ after out-of-range wr ptr */
++#define BUG5475_WORKAROUND 1 /* 10G SNAP encapsulation broken */
++#define BUG5762_WORKAROUND 1 /* Set all queues to jumbo mode */
++#define BUG5391_WORKAROUND 1 /* Misaligned TX can't span 512-byte boundary */
++#define BUG7916_WORKAROUND 1 /* RX flush gets lost */
++
++#endif /* B0/A01 */
++
++#else
++# error Need hw support.
++#endif
++
++#endif /* __CI_DRIVER_EFAB_WORKAROUNDS_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,199 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC hardware interface.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_HARDWARE_H__
++#define __CI_DRIVER_EFAB_HARDWARE_H__
++
++#include "ci/driver/efab/hardware/workarounds.h"
++#include <ci/efhw/hardware_sysdep.h>
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Common EtherFabric definitions
++ *
++ *---------------------------------------------------------------------------*/
++
++#include <ci/efhw/debug.h>
++#include <ci/efhw/common.h>
++#include <ci/driver/efab/hardware/common.h>
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric varients
++ *
++ *---------------------------------------------------------------------------*/
++
++#include <ci/driver/efab/hardware/falcon.h>
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric Portable Hardware Layer defines
++ *
++ *---------------------------------------------------------------------------*/
++
++ /*-------------- Initialisation ------------ */
++#define efhw_nic_close_hardware(nic) \
++ ((nic)->efhw_func->close_hardware(nic))
++
++#define efhw_nic_init_hardware(nic, ev_handlers, mac_addr) \
++ ((nic)->efhw_func->init_hardware((nic), (ev_handlers), (mac_addr)))
++
++/*-------------- Interrupt support ------------ */
++/** Handle interrupt. Return 0 if not handled, 1 if handled. */
++#define efhw_nic_interrupt(nic) \
++ ((nic)->efhw_func->interrupt(nic))
++
++#define efhw_nic_interrupt_enable(nic, index) \
++ ((nic)->efhw_func->interrupt_enable(nic, index))
++
++#define efhw_nic_interrupt_disable(nic, index) \
++ ((nic)->efhw_func->interrupt_disable(nic, index))
++
++#define efhw_nic_set_interrupt_moderation(nic, index, val) \
++ ((nic)->efhw_func->set_interrupt_moderation(nic, index, val))
++
++/*-------------- Event support ------------ */
++
++#define efhw_nic_event_queue_enable(nic, evq, size, q_base, buf_base) \
++ ((nic)->efhw_func->event_queue_enable(nic, evq, size, q_base, \
++ buf_base))
++
++#define efhw_nic_event_queue_disable(nic, evq, timer_only) \
++ ((nic)->efhw_func->event_queue_disable(nic, evq, timer_only))
++
++#define efhw_nic_wakeup_request(nic, q_base, index, evq) \
++ ((nic)->efhw_func->wakeup_request(nic, q_base, index, evq))
++
++#define efhw_nic_sw_event(nic, data, ev) \
++ ((nic)->efhw_func->sw_event(nic, data, ev))
++
++/*-------------- Filter support ------------ */
++#define efhw_nic_ipfilter_set(nic, type, index, dmaq, \
++ saddr, sport, daddr, dport) \
++ ((nic)->efhw_func->ipfilter_set(nic, type, index, dmaq, \
++ saddr, sport, daddr, dport))
++
++#define efhw_nic_ipfilter_attach(nic, index, dmaq) \
++ ((nic)->efhw_func->ipfilter_attach(nic, index, dmaq))
++
++#define efhw_nic_ipfilter_detach(nic, index) \
++ ((nic)->efhw_func->ipfilter_detach(nic, index))
++
++#define efhw_nic_ipfilter_clear(nic, index) \
++ ((nic)->efhw_func->ipfilter_clear(nic, index))
++
++/*-------------- DMA support ------------ */
++#define efhw_nic_dmaq_tx_q_init(nic, dmaq, evq, owner, tag, \
++ dmaq_size, index, flags) \
++ ((nic)->efhw_func->dmaq_tx_q_init(nic, dmaq, evq, owner, tag, \
++ dmaq_size, index, flags))
++
++#define efhw_nic_dmaq_rx_q_init(nic, dmaq, evq, owner, tag, \
++ dmaq_size, index, flags) \
++ ((nic)->efhw_func->dmaq_rx_q_init(nic, dmaq, evq, owner, tag, \
++ dmaq_size, index, flags))
++
++#define efhw_nic_dmaq_tx_q_disable(nic, dmaq) \
++ ((nic)->efhw_func->dmaq_tx_q_disable(nic, dmaq))
++
++#define efhw_nic_dmaq_rx_q_disable(nic, dmaq) \
++ ((nic)->efhw_func->dmaq_rx_q_disable(nic, dmaq))
++
++#define efhw_nic_flush_tx_dma_channel(nic, dmaq) \
++ ((nic)->efhw_func->flush_tx_dma_channel(nic, dmaq))
++
++#define efhw_nic_flush_rx_dma_channel(nic, dmaq) \
++ ((nic)->efhw_func->flush_rx_dma_channel(nic, dmaq))
++
++/*-------------- MAC Low level interface ---- */
++#define efhw_gmac_get_mac_addr(nic) \
++ ((nic)->gmac->get_mac_addr((nic)->gmac))
++
++/*-------------- Buffer table -------------- */
++#define efhw_nic_buffer_table_set(nic, addr, bufsz, region, \
++ own_id, buf_id) \
++ ((nic)->efhw_func->buffer_table_set(nic, addr, bufsz, region, \
++ own_id, buf_id))
++
++#define efhw_nic_buffer_table_set_n(nic, buf_id, addr, bufsz, \
++ region, n_pages, own_id) \
++ ((nic)->efhw_func->buffer_table_set_n(nic, buf_id, addr, bufsz, \
++ region, n_pages, own_id))
++
++#define efhw_nic_buffer_table_clear(nic, id, num) \
++ ((nic)->efhw_func->buffer_table_clear(nic, id, num))
++
++#define efhw_nic_buffer_table_commit(nic) \
++ ((nic)->efhw_func->buffer_table_commit(nic))
++
++/*----------------------------------------------------------------------------
++ * Hardware specific portability macros for performance critical code.
++ *
++ * Warning: and driver code which is using these defines is not
++ * capable of supporting multiple NIC varients and should be built and
++ * marked appropriately
++ *
++ *---------------------------------------------------------------------------*/
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++
++/* --- DMA --- */
++#define EFHW_DMA_ADDRMASK (0xffffffffffffffffULL)
++
++/* --- Buffers --- */
++#define EFHW_BUFFER_ADDR FALCON_BUFFER_4K_ADDR
++#define EFHW_BUFFER_PAGE FALCON_BUFFER_4K_PAGE
++#define EFHW_BUFFER_OFF FALCON_BUFFER_4K_OFF
++
++/* --- Filters --- */
++#define EFHW_IP_FILTER_NUM FALCON_FILTER_TBL_NUM
++
++#define EFHW_MAX_PAGE_SIZE FALCON_MAX_PAGE_SIZE
++
++#else
++# error no hardware definition found
++#endif
++
++#if PAGE_SIZE <= EFHW_MAX_PAGE_SIZE
++#define EFHW_NIC_PAGE_SIZE PAGE_SIZE
++#else
++#define EFHW_NIC_PAGE_SIZE EFHW_MAX_PAGE_SIZE
++#endif
++#define EFHW_NIC_PAGE_MASK (~(EFHW_NIC_PAGE_SIZE-1))
++
++#endif /* __CI_DRIVER_EFAB_HARDWARE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,276 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains public EFX VI API to Solarflare resource manager.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_RESOURCE_EFX_VI_H__
++#define __CI_DRIVER_RESOURCE_EFX_VI_H__
++
++/* Default size of event queue in the efx_vi resource. Copied from
++ * CI_CFG_NETIF_EVENTQ_SIZE */
++#define EFX_VI_EVENTQ_SIZE_DEFAULT 1024
++
++extern int efx_vi_eventq_size;
++
++/**************************************************************************
++ * efx_vi_state types, allocation and free
++ **************************************************************************/
++
++/*! Handle for refering to a efx_vi */
++struct efx_vi_state;
++
++/*!
++ * Allocate an efx_vi, including event queue and pt_endpoint
++ *
++ * \param vih_out Pointer to a handle that is set on success
++ * \param nic_index Index of NIC to apply this resource to
++ * \return Zero on success (and vih_out set), non-zero on failure.
++ */
++extern int
++efx_vi_alloc(struct efx_vi_state **vih_out, int nic_index);
++
++/*!
++ * Free a previously allocated efx_vi
++ *
++ * \param vih The handle of the efx_vi to free
++ */
++extern void
++efx_vi_free(struct efx_vi_state *vih);
++
++/*!
++ * Reset a previously allocated efx_vi
++ *
++ * \param vih The handle of the efx_vi to reset
++ */
++extern void
++efx_vi_reset(struct efx_vi_state *vih);
++
++/**************************************************************************
++ * efx_vi_eventq types and functions
++ **************************************************************************/
++
++/*!
++ * Register a function to receive callbacks when event queue timeouts
++ * or wakeups occur. Only one function per efx_vi can be registered
++ * at once.
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param callback The function to callback
++ * \param context An argument to pass to the callback function
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_eventq_register_callback(struct efx_vi_state *vih,
++ void (*callback)(void *context, int is_timeout),
++ void *context);
++
++/*!
++ * Remove the current eventq timeout or wakeup callback function
++ *
++ * \param vih The handle to identify the efx_vi
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_eventq_kill_callback(struct efx_vi_state *vih);
++
++/**************************************************************************
++ * efx_vi_dma_map types and functions
++ **************************************************************************/
++
++/*!
++ * Handle for refering to a efx_vi
++ */
++struct efx_vi_dma_map_state;
++
++/*!
++ * Map a list of buffer pages so they are registered with the hardware
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param addrs An array of page pointers to map
++ * \param n_addrs Length of the page pointer array. Must be a power of two.
++ * \param dmh_out Set on success to a handle used to refer to this mapping
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_dma_map_pages(struct efx_vi_state *vih, struct page **pages,
++ int n_pages, struct efx_vi_dma_map_state **dmh_out);
++extern int
++efx_vi_dma_map_addrs(struct efx_vi_state *vih,
++ unsigned long long *dev_bus_addrs, int n_pages,
++ struct efx_vi_dma_map_state **dmh_out);
++
++/*!
++ * Unmap a previously mapped set of pages so they are no longer registered
++ * with the hardware.
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param dmh The handle to identify the dma mapping
++ */
++extern void
++efx_vi_dma_unmap_pages(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh);
++extern void
++efx_vi_dma_unmap_addrs(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh);
++
++/*!
++ * Retrieve the buffer address of the mapping
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param dmh The handle to identify the buffer mapping
++ * \return The buffer address on success, or zero on failure
++ */
++extern unsigned
++efx_vi_dma_get_map_addr(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh);
++
++/**************************************************************************
++ * efx_vi filter functions
++ **************************************************************************/
++
++#define EFX_VI_STATIC_FILTERS 32
++
++/*! Handle to refer to a filter instance */
++struct filter_resource_t;
++
++/*!
++ * Allocate and add a filter
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param protocol The protocol of the new filter: UDP or TCP
++ * \param ip_addr_be32 The local ip address of the filter
++ * \param port_le16 The local port of the filter
++ * \param fh_out Set on success to be a handle to refer to this filter
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_filter(struct efx_vi_state *vih, int protocol, unsigned ip_addr_be32,
++ int port_le16, struct filter_resource_t **fh_out);
++
++/*!
++ * Remove a filter and free resources associated with it
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param fh The handle to identify the filter
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_filter_stop(struct efx_vi_state *vih, struct filter_resource_t *fh);
++
++/**************************************************************************
++ * efx_vi hw resources types and functions
++ **************************************************************************/
++
++/*! Constants for the type field in efx_vi_hw_resource */
++#define EFX_VI_HW_RESOURCE_TXDMAQ 0x0 /* PFN of TX DMA Q */
++#define EFX_VI_HW_RESOURCE_RXDMAQ 0x1 /* PFN of RX DMA Q */
++#define EFX_VI_HW_RESOURCE_TXBELL 0x2 /* PFN of TX Doorbell (EF1) */
++#define EFX_VI_HW_RESOURCE_RXBELL 0x3 /* PFN of RX Doorbell (EF1) */
++#define EFX_VI_HW_RESOURCE_EVQTIMER 0x4 /* Address of event q timer */
++
++/* Address of event q pointer (EF1) */
++#define EFX_VI_HW_RESOURCE_EVQPTR 0x5
++/* Address of register pointer (Falcon A) */
++#define EFX_VI_HW_RESOURCE_EVQRPTR 0x6
++/* Offset of register pointer (Falcon B) */
++#define EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET 0x7
++/* Address of mem KVA */
++#define EFX_VI_HW_RESOURCE_EVQMEMKVA 0x8
++/* PFN of doorbell page (Falcon) */
++#define EFX_VI_HW_RESOURCE_BELLPAGE 0x9
++
++/*! How large an array to allocate for the get_() functions - smaller
++ than the total number of constants as some are mutually exclusive */
++#define EFX_VI_HW_RESOURCE_MAXSIZE 0x7
++
++/*! Constants for the mem_type field in efx_vi_hw_resource */
++#define EFX_VI_HW_RESOURCE_IOBUFFER 0 /* Host memory */
++#define EFX_VI_HW_RESOURCE_PERIPHERAL 1 /* Card memory/registers */
++
++/*!
++ * Data structure providing information on a hardware resource mapping
++ */
++struct efx_vi_hw_resource {
++ u8 type; /*!< What this resource represents */
++ u8 mem_type; /*!< What type of memory is it in, eg,
++ * host or iomem */
++ u8 more_to_follow; /*!< Is this part of a multi-region resource */
++ u32 length; /*!< Length of the resource in bytes */
++ unsigned long address; /*!< Address of this resource */
++};
++
++/*!
++ * Metadata concerning the list of hardware resource mappings
++ */
++struct efx_vi_hw_resource_metadata {
++ int version;
++ int evq_order;
++ int evq_offs;
++ int evq_capacity;
++ int instance;
++ unsigned rx_capacity;
++ unsigned tx_capacity;
++ int nic_arch;
++ int nic_revision;
++ char nic_variant;
++};
++
++/*!
++ * Obtain a list of hardware resource mappings, using virtual addresses
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param mdata Pointer to a structure to receive the metadata
++ * \param hw_res_array An array to receive the list of hardware resources
++ * \param length The length of hw_res_array. Updated on success to contain
++ * the number of entries in the supplied array that were used.
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_hw_resource_get_virt(struct efx_vi_state *vih,
++ struct efx_vi_hw_resource_metadata *mdata,
++ struct efx_vi_hw_resource *hw_res_array,
++ int *length);
++
++/*!
++ * Obtain a list of hardware resource mappings, using physical addresses
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param mdata Pointer to a structure to receive the metadata
++ * \param hw_res_array An array to receive the list of hardware resources
++ * \param length The length of hw_res_array. Updated on success to contain
++ * the number of entries in the supplied array that were used.
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_hw_resource_get_phys(struct efx_vi_state *vih,
++ struct efx_vi_hw_resource_metadata *mdata,
++ struct efx_vi_hw_resource *hw_res_array,
++ int *length);
++
++#endif /* __CI_DRIVER_RESOURCE_EFX_VI_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,76 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains definition of the public type struct linux_efhw_nic.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_RESOURCE_LINUX_RESOURCE__
++#define __CI_DRIVER_RESOURCE_LINUX_RESOURCE__
++
++#ifndef __linux__
++# error Silly
++#endif
++#ifndef __KERNEL__
++# error Silly
++#endif
++
++#include <ci/efhw/efhw_types.h>
++#include <linux/interrupt.h>
++
++
++/************************************************************************
++ * Per-nic structure in the resource driver *
++ ************************************************************************/
++
++struct linux_efhw_nic {
++ struct efhw_nic nic;
++
++ struct pci_dev *pci_dev; /*!< pci descriptor */
++ struct tasklet_struct tasklet; /*!< for interrupt bottom half */
++
++ /* Physical addresses of the control aperture bar. */
++ unsigned long ctr_ap_pci_addr;
++
++ /*! Callbacks for driverlink, when needed. */
++ struct efx_dl_callbacks *dl_callbacks;
++
++ /*! Event handlers. */
++ struct efhw_ev_handler *ev_handlers;
++
++};
++
++#define linux_efhw_nic(efhw_nic) \
++ container_of(efhw_nic, struct linux_efhw_nic, nic)
++
++#endif /* __CI_DRIVER_RESOURCE_LINUX_RESOURCE__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/checks.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/checks.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/checks.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/checks.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,118 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides helpers to turn bit shifts into dword shifts and
++ * check that the bit fields haven't overflown the dword etc.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_CHECK_H__
++#define __CI_EFHW_CHECK_H__
++
++/*----------------------------------------------------------------------------
++ *
++ * Helpers to turn bit shifts into dword shifts and check that the bit fields
++ * haven't overflown the dword etc. Aim is to preserve consistency with the
++ * autogenerated headers - once stable we could hard code.
++ *
++ *---------------------------------------------------------------------------*/
++
++/* mask constructors */
++#define __FALCON_MASK(WIDTH, T) ((((T)1) << (WIDTH)) - 1)
++#define __FALCON_MASK32(WIDTH) __FALCON_MASK((WIDTH), uint32_t)
++#define __FALCON_MASK64(WIDTH) __FALCON_MASK((WIDTH), uint64_t)
++
++#define __FALCON_MASKFIELD32(LBN, WIDTH) \
++ ((uint32_t)(__FALCON_MASK32(WIDTH) << (LBN)))
++
++/* constructors for fields which span the first and second dwords */
++#define __LW(LBN) (32 - LBN)
++#define __LOW(v, LBN, WIDTH) \
++ ((uint32_t)(((v) & __FALCON_MASK64(__LW((LBN)))) << (LBN)))
++#define __HIGH(v, LBN, WIDTH) \
++ ((uint32_t)(((v) >> __LW((LBN))) & \
++ __FALCON_MASK64((WIDTH - __LW((LBN))))))
++/* constructors for fields within the second dword */
++#define __DW2(LBN) ((LBN) - 32)
++
++/* constructors for fields which span the second and third dwords */
++#define __LW2(LBN) (64 - LBN)
++#define __LOW2(v, LBN, WIDTH) \
++ ((uint32_t)(((v) & __FALCON_MASK64(__LW2((LBN)))) << ((LBN) - 32)))
++#define __HIGH2(v, LBN, WIDTH) \
++ ((uint32_t)(((v) >> __LW2((LBN))) & \
++ __FALCON_MASK64((WIDTH - __LW2((LBN))))))
++
++/* constructors for fields within the third dword */
++#define __DW3(LBN) ((LBN) - 64)
++
++/* constructors for fields which span the third and fourth dwords */
++#define __LW3(LBN) (96 - LBN)
++#define __LOW3(v, LBN, WIDTH) \
++ ((uint32_t)(((v) & __FALCON_MASK64(__LW3((LBN)))) << ((LBN) - 64)))
++#define __HIGH3(v, LBN, WIDTH) \
++ ((ci_unit32)(((v) >> __LW3((LBN))) & \
++ __FALCON_MASK64((WIDTH - __LW3((LBN))))))
++
++/* constructors for fields within the fourth dword */
++#define __DW4(LBN) ((LBN) - 96)
++
++/* checks that the autogenerated headers are consistent with our model */
++#define __WIDTHCHCK(a, b) EFHW_ASSERT((a) == (b))
++#define __RANGECHCK(v, WIDTH) \
++ EFHW_ASSERT(((uint64_t)(v) & ~(__FALCON_MASK64((WIDTH)))) == 0)
++
++/* fields within the first dword */
++#define __DWCHCK(LBN, WIDTH) \
++ EFHW_ASSERT(((LBN) >= 0) && (((LBN)+(WIDTH)) <= 32))
++
++/* fields which span the first and second dwords */
++#define __LWCHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW(LBN))
++
++/* fields within the second dword */
++#define __DW2CHCK(LBN, WIDTH) \
++ EFHW_ASSERT(((LBN) >= 32) && (((LBN)+(WIDTH)) <= 64))
++
++/* fields which span the second and third dwords */
++#define __LW2CHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW2(LBN))
++
++/* fields within the third dword */
++#define __DW3CHCK(LBN, WIDTH) \
++ EFHW_ASSERT(((LBN) >= 64) && (((LBN)+(WIDTH)) <= 96))
++
++/* fields which span the third and fourth dwords */
++#define __LW3CHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW3(LBN))
++
++/* fields within the fourth dword */
++#define __DW4CHCK(LBN, WIDTH) \
++ EFHW_ASSERT(((LBN) >= 96) && (((LBN)+(WIDTH)) <= 128))
++
++/* fields in the first qword */
++#define __QWCHCK(LBN, WIDTH) \
++ EFHW_ASSERT(((LBN) >= 0) && (((LBN)+(WIDTH)) <= 64))
++
++#endif /* __CI_EFHW_CHECK_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/common.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/common.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/common.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,102 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides API of the efhw library which may be used both from
++ * the kernel and from the user-space code.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_COMMON_H__
++#define __CI_EFHW_COMMON_H__
++
++#include <ci/efhw/common_sysdep.h>
++
++enum efhw_arch {
++ EFHW_ARCH_FALCON,
++ EFHW_ARCH_SIENA,
++};
++
++typedef uint32_t efhw_buffer_addr_t;
++#define EFHW_BUFFER_ADDR_FMT "[ba:%"PRIx32"]"
++
++/*! Comment? */
++typedef union {
++ uint64_t u64;
++ struct {
++ uint32_t a;
++ uint32_t b;
++ } opaque;
++ struct {
++ uint32_t code;
++ uint32_t status;
++ } ev1002;
++} efhw_event_t;
++
++/* Flags for TX/RX queues */
++#define EFHW_VI_JUMBO_EN 0x01 /*! scatter RX over multiple desc */
++#define EFHW_VI_ISCSI_RX_HDIG_EN 0x02 /*! iscsi rx header digest */
++#define EFHW_VI_ISCSI_TX_HDIG_EN 0x04 /*! iscsi tx header digest */
++#define EFHW_VI_ISCSI_RX_DDIG_EN 0x08 /*! iscsi rx data digest */
++#define EFHW_VI_ISCSI_TX_DDIG_EN 0x10 /*! iscsi tx data digest */
++#define EFHW_VI_TX_PHYS_ADDR_EN 0x20 /*! TX physical address mode */
++#define EFHW_VI_RX_PHYS_ADDR_EN 0x40 /*! RX physical address mode */
++#define EFHW_VI_RM_WITH_INTERRUPT 0x80 /*! VI with an interrupt */
++#define EFHW_VI_TX_IP_CSUM_DIS 0x100 /*! enable ip checksum generation */
++#define EFHW_VI_TX_TCPUDP_CSUM_DIS 0x200 /*! enable tcp/udp checksum
++ generation */
++#define EFHW_VI_TX_TCPUDP_ONLY 0x400 /*! drop non-tcp/udp packets */
++
++/* Types of hardware filter */
++/* Each of these values implicitly selects scatter filters on B0 - or in
++ EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK if a non-scatter filter is required */
++#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD (0) /* dest host only */
++#define EFHW_IP_FILTER_TYPE_UDP_FULL (1) /* dest host and port */
++#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD (2) /* dest based filter */
++#define EFHW_IP_FILTER_TYPE_TCP_FULL (3) /* src filter */
++/* Same again, but with RSS (for B0 only) */
++#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD_RSS_B0 (4)
++#define EFHW_IP_FILTER_TYPE_UDP_FULL_RSS_B0 (5)
++#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD_RSS_B0 (6)
++#define EFHW_IP_FILTER_TYPE_TCP_FULL_RSS_B0 (7)
++
++#define EFHW_IP_FILTER_TYPE_FULL_MASK (0x1) /* Mask for full / wildcard */
++#define EFHW_IP_FILTER_TYPE_TCP_MASK (0x2) /* Mask for TCP type */
++#define EFHW_IP_FILTER_TYPE_RSS_B0_MASK (0x4) /* Mask for B0 RSS enable */
++#define EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK (0x8) /* Mask for B0 SCATTER dsbl */
++
++#define EFHW_IP_FILTER_TYPE_MASK (0xffff) /* Mask of types above */
++
++#define EFHW_IP_FILTER_BROADCAST (0x10000) /* driverlink filter
++ support */
++
++#endif /* __CI_EFHW_COMMON_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,71 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for
++ * userland-to-kernel interfaces.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_COMMON_LINUX_H__
++#define __CI_EFHW_COMMON_LINUX_H__
++
++#include <linux/types.h>
++#include <linux/version.h>
++
++/* Dirty hack, but Linux kernel does not provide DMA_ADDR_T_FMT */
++#if BITS_PER_LONG == 64 || defined(CONFIG_HIGHMEM64G)
++#define DMA_ADDR_T_FMT "%llx"
++#else
++#define DMA_ADDR_T_FMT "%x"
++#endif
++
++/* Linux kernel also does not provide PRIx32... Sigh. */
++#define PRIx32 "x"
++
++#ifdef __ia64__
++# define PRIx64 "lx"
++#else
++# define PRIx64 "llx"
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++enum {
++ false = 0,
++ true = 1
++};
++
++typedef _Bool bool;
++#endif /* LINUX_VERSION_CODE < 2.6.19 */
++
++#endif /* __CI_EFHW_COMMON_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/debug.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/debug.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/debug.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,84 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides debug-related API for efhw library using Linux kernel
++ * primitives.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_DEBUG_LINUX_H__
++#define __CI_EFHW_DEBUG_LINUX_H__
++
++#define EFHW_PRINTK_PREFIX "[sfc efhw] "
++
++#define EFHW_PRINTK(level, fmt, ...) \
++ printk(level EFHW_PRINTK_PREFIX fmt "\n", __VA_ARGS__)
++
++/* Following macros should be used with non-zero format parameters
++ * due to __VA_ARGS__ limitations. Use "%s" with __FUNCTION__ if you can't
++ * find better parameters. */
++#define EFHW_ERR(fmt, ...) EFHW_PRINTK(KERN_ERR, fmt, __VA_ARGS__)
++#define EFHW_WARN(fmt, ...) EFHW_PRINTK(KERN_WARNING, fmt, __VA_ARGS__)
++#define EFHW_NOTICE(fmt, ...) EFHW_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__)
++#if 0 && !defined(NDEBUG)
++#define EFHW_TRACE(fmt, ...) EFHW_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__)
++#else
++#define EFHW_TRACE(fmt, ...)
++#endif
++
++#ifndef NDEBUG
++#define EFHW_ASSERT(cond) BUG_ON((cond) == 0)
++#define EFHW_DO_DEBUG(expr) expr
++#else
++#define EFHW_ASSERT(cond)
++#define EFHW_DO_DEBUG(expr)
++#endif
++
++#define EFHW_TEST(expr) \
++ do { \
++ if (unlikely(!(expr))) \
++ BUG(); \
++ } while (0)
++
++/* Build time asserts. We paste the line number into the type name
++ * so that the macro can be used more than once per file even if the
++ * compiler objects to multiple identical typedefs. Collisions
++ * between use in different header files is still possible. */
++#ifndef EFHW_BUILD_ASSERT
++#define __EFHW_BUILD_ASSERT_NAME(_x) __EFHW_BUILD_ASSERT_ILOATHECPP(_x)
++#define __EFHW_BUILD_ASSERT_ILOATHECPP(_x) __EFHW_BUILD_ASSERT__ ##_x
++#define EFHW_BUILD_ASSERT(e) \
++ typedef char __EFHW_BUILD_ASSERT_NAME(__LINE__)[(e) ? 1 : -1]
++#endif
++
++#endif /* __CI_EFHW_DEBUG_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,43 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides some limits used in both kernel and userland code.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EFAB_CONFIG_H__
++#define __CI_EFHW_EFAB_CONFIG_H__
++
++#define EFHW_MAX_NR_DEVS 5 /* max number of efhw devices supported */
++
++#endif /* __CI_EFHW_EFAB_CONFIG_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,342 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides struct efhw_nic and some related types.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EFAB_TYPES_H__
++#define __CI_EFHW_EFAB_TYPES_H__
++
++#include <ci/efhw/efhw_config.h>
++#include <ci/efhw/hardware_sysdep.h>
++#include <ci/efhw/iopage_types.h>
++#include <ci/efhw/sysdep.h>
++
++/*--------------------------------------------------------------------
++ *
++ * hardware limits used in the types
++ *
++ *--------------------------------------------------------------------*/
++
++#define EFHW_KEVENTQ_MAX 8
++
++/*--------------------------------------------------------------------
++ *
++ * forward type declarations
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_nic;
++
++/*--------------------------------------------------------------------
++ *
++ * Managed interface
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_buffer_table_allocation{
++ unsigned base;
++ unsigned order;
++};
++
++struct eventq_resource_hardware {
++ /*!iobuffer allocated for eventq - can be larger than eventq */
++ efhw_iopages_t iobuff;
++ unsigned iobuff_off;
++ struct efhw_buffer_table_allocation buf_tbl_alloc;
++ int capacity; /*!< capacity of event queue */
++};
++
++/*--------------------------------------------------------------------
++ *
++ * event queues and event driven callbacks
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_keventq {
++ volatile int lock;
++ caddr_t evq_base;
++ int32_t evq_ptr;
++ uint32_t evq_mask;
++ unsigned instance;
++ struct eventq_resource_hardware hw;
++ struct efhw_ev_handler *ev_handlers;
++};
++
++/**********************************************************************
++ * Portable HW interface. ***************************************
++ **********************************************************************/
++
++/*--------------------------------------------------------------------
++ *
++ * EtherFabric Functional units - configuration and control
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_func_ops {
++
++ /*-------------- Initialisation ------------ */
++
++ /*! close down all hardware functional units - leaves NIC in a safe
++ state for driver unload */
++ void (*close_hardware) (struct efhw_nic *nic);
++
++ /*! initialise all hardware functional units */
++ int (*init_hardware) (struct efhw_nic *nic,
++ struct efhw_ev_handler *,
++ const uint8_t *mac_addr);
++
++ /*-------------- Interrupt support ------------ */
++
++ /*! Main interrupt routine
++ ** This function returns,
++ ** - zero, if the IRQ was not generated by EF1
++ ** - non-zero, if EF1 was the source of the IRQ
++ **
++ **
++ ** opaque is an OS provided pointer for use by the OS callbacks
++ ** e.g in Windows used to indicate DPC scheduled
++ */
++ int (*interrupt) (struct efhw_nic *nic);
++
++ /*! Enable given interrupt mask for the given IRQ unit */
++ void (*interrupt_enable) (struct efhw_nic *nic, uint idx);
++
++ /*! Disable given interrupt mask for the given IRQ unit */
++ void (*interrupt_disable) (struct efhw_nic *nic, uint idx);
++
++ /*! Set interrupt moderation strategy for the given IRQ unit
++ ** val is in usec
++ */
++ void (*set_interrupt_moderation)(struct efhw_nic *nic,
++ uint idx, uint val);
++
++ /*-------------- Event support ------------ */
++
++ /*! Enable the given event queue
++ depending on the underlying implementation (EF1 or Falcon) then
++ either a q_base_addr in host memory, or a buffer base id should
++ be proivded
++ */
++ void (*event_queue_enable) (struct efhw_nic *nic,
++ uint evq, /* evnt queue index */
++ uint evq_size, /* units of #entries */
++ dma_addr_t q_base_addr, uint buf_base_id);
++
++ /*! Disable the given event queue (and any associated timer) */
++ void (*event_queue_disable) (struct efhw_nic *nic, uint evq,
++ int timer_only);
++
++ /*! request wakeup from the NIC on a given event Q */
++ void (*wakeup_request) (struct efhw_nic *nic, dma_addr_t q_base_addr,
++ int next_i, int evq);
++
++ /*! Push a SW event on a given eventQ */
++ void (*sw_event) (struct efhw_nic *nic, int data, int evq);
++
++ /*-------------- Filter support ------------ */
++
++ /*! Setup a given filter - The software can request a filter_i,
++ * but some EtherFabric implementations will override with
++ * a more suitable index
++ */
++ int (*ipfilter_set) (struct efhw_nic *nic, int type,
++ int *filter_i, int dmaq,
++ unsigned saddr_be32, unsigned sport_be16,
++ unsigned daddr_be32, unsigned dport_be16);
++
++ /*! Attach a given filter to a DMAQ */
++ void (*ipfilter_attach) (struct efhw_nic *nic, int filter_idx,
++ int dmaq_idx);
++
++ /*! Detach a filter from its DMAQ */
++ void (*ipfilter_detach) (struct efhw_nic *nic, int filter_idx);
++
++ /*! Clear down a given filter */
++ void (*ipfilter_clear) (struct efhw_nic *nic, int filter_idx);
++
++ /*-------------- DMA support ------------ */
++
++ /*! Initialise NIC state for a given TX DMAQ */
++ void (*dmaq_tx_q_init) (struct efhw_nic *nic,
++ uint dmaq, uint evq, uint owner, uint tag,
++ uint dmaq_size, uint buf_idx, uint flags);
++
++ /*! Initialise NIC state for a given RX DMAQ */
++ void (*dmaq_rx_q_init) (struct efhw_nic *nic,
++ uint dmaq, uint evq, uint owner, uint tag,
++ uint dmaq_size, uint buf_idx, uint flags);
++
++ /*! Disable a given TX DMAQ */
++ void (*dmaq_tx_q_disable) (struct efhw_nic *nic, uint dmaq);
++
++ /*! Disable a given RX DMAQ */
++ void (*dmaq_rx_q_disable) (struct efhw_nic *nic, uint dmaq);
++
++ /*! Flush a given TX DMA channel */
++ int (*flush_tx_dma_channel) (struct efhw_nic *nic, uint dmaq);
++
++ /*! Flush a given RX DMA channel */
++ int (*flush_rx_dma_channel) (struct efhw_nic *nic, uint dmaq);
++
++ /*-------------- Buffer table Support ------------ */
++
++ /*! Initialise a buffer table page */
++ void (*buffer_table_set) (struct efhw_nic *nic,
++ dma_addr_t dma_addr,
++ uint bufsz, uint region,
++ int own_id, int buffer_id);
++
++ /*! Initialise a block of buffer table pages */
++ void (*buffer_table_set_n) (struct efhw_nic *nic, int buffer_id,
++ dma_addr_t dma_addr,
++ uint bufsz, uint region,
++ int n_pages, int own_id);
++
++ /*! Clear a block of buffer table pages */
++ void (*buffer_table_clear) (struct efhw_nic *nic, int buffer_id,
++ int num);
++
++ /*! Commit a buffer table update */
++ void (*buffer_table_commit) (struct efhw_nic *nic);
++
++};
++
++
++/*----------------------------------------------------------------------------
++ *
++ * NIC type
++ *
++ *---------------------------------------------------------------------------*/
++
++struct efhw_device_type {
++ int arch; /* enum efhw_arch */
++ char variant; /* 'A', 'B', ... */
++ int revision; /* 0, 1, ... */
++};
++
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric NIC instance - nic.c for HW independent functions
++ *
++ *---------------------------------------------------------------------------*/
++
++/*! */
++struct efhw_nic {
++ /*! zero base index in efrm_nic_table.nic array */
++ volatile int index;
++ int ifindex; /*!< OS level nic index */
++#ifdef HAS_NET_NAMESPACE
++ struct net *nd_net;
++#endif
++
++ struct efhw_device_type devtype;
++
++ /*! Options that can be set by user. */
++ unsigned options;
++# define NIC_OPT_EFTEST 0x1 /* owner is an eftest app */
++
++# define NIC_OPT_DEFAULT 0
++
++ /*! Internal flags that indicate hardware properties at runtime. */
++ unsigned flags;
++# define NIC_FLAG_NO_INTERRUPT 0x01 /* to be set at init time only */
++# define NIC_FLAG_TRY_MSI 0x02
++# define NIC_FLAG_MSI 0x04
++# define NIC_FLAG_OS_IRQ_EN 0x08
++# define NIC_FLAG_10G 0x10
++
++ unsigned mtu; /*!< MAC MTU (includes MAC hdr) */
++
++ /* hardware resources */
++
++ /*! I/O address of the start of the bar */
++ efhw_ioaddr_t bar_ioaddr;
++
++ /*! Bar number of control aperture. */
++ unsigned ctr_ap_bar;
++ /*! Length of control aperture in bytes. */
++ unsigned ctr_ap_bytes;
++
++ uint8_t mac_addr[ETH_ALEN]; /*!< mac address */
++
++ /*! EtherFabric Functional Units -- functions */
++ const struct efhw_func_ops *efhw_func;
++
++ /* Value read from FPGA version register. Zero for asic. */
++ unsigned fpga_version;
++
++ /*! This lock protects a number of misc NIC resources. It should
++ * only be used for things that can be at the bottom of the lock
++ * order. ie. You mustn't attempt to grab any other lock while
++ * holding this one.
++ */
++ spinlock_t *reg_lock;
++ spinlock_t the_reg_lock;
++
++ int buf_commit_outstanding; /*!< outstanding buffer commits */
++
++ /*! interrupt callbacks (hard-irq) */
++ void (*irq_handler) (struct efhw_nic *, int unit);
++
++ /*! event queues per driver */
++ struct efhw_keventq evq[EFHW_KEVENTQ_MAX];
++
++/* for marking when we are not using an IRQ unit
++ - 0 is a valid offset to an IRQ unit on EF1! */
++#define EFHW_IRQ_UNIT_UNUSED 0xffff
++ /*! interrupt unit in use */
++ unsigned int irq_unit[EFHW_KEVENTQ_MAX];
++ efhw_iopage_t irq_iobuff; /*!< Falcon SYSERR interrupt */
++
++ /* The new driverlink infrastructure. */
++ struct efx_dl_device *net_driver_dev;
++ struct efx_dlfilt_cb_s *dlfilter_cb;
++
++ /*! Bit masks of the sizes of event queues and dma queues supported
++ * by the nic. */
++ unsigned evq_sizes;
++ unsigned rxq_sizes;
++ unsigned txq_sizes;
++
++ /* Size of filter table (including odd and even banks). */
++ unsigned filter_tbl_size;
++};
++
++
++#define EFHW_KVA(nic) ((nic)->bar_ioaddr)
++
++
++#endif /* __CI_EFHW_EFHW_TYPES_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,73 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains API provided by efhw/eventq.c file. This file is not
++ * designed for use outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EVENTQ_H__
++#define __CI_EFHW_EVENTQ_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efhw/eventq_macros.h>
++
++/*! Poll the event queue. */
++extern int efhw_keventq_poll(struct efhw_nic *, struct efhw_keventq *);
++
++/*! Callbacks for handling events. */
++struct efhw_ev_handler {
++ void (*wakeup_fn)(struct efhw_nic *nic, efhw_event_t *ev);
++ void (*timeout_fn)(struct efhw_nic *nic, efhw_event_t *ev);
++ void (*sw_fn)(struct efhw_nic *nic, efhw_event_t *ev);
++ void (*dmaq_flushed_fn) (struct efhw_nic *, int, int);
++};
++
++extern int efhw_keventq_ctor(struct efhw_nic *, int instance,
++ struct efhw_keventq *, struct efhw_ev_handler *);
++extern void efhw_keventq_dtor(struct efhw_nic *, struct efhw_keventq *);
++
++extern void efhw_handle_txdmaq_flushed(struct efhw_nic *,
++ struct efhw_ev_handler *,
++ efhw_event_t *);
++extern void efhw_handle_rxdmaq_flushed(struct efhw_nic *,
++ struct efhw_ev_handler *,
++ efhw_event_t *);
++extern void efhw_handle_wakeup_event(struct efhw_nic *,
++ struct efhw_ev_handler *,
++ efhw_event_t *);
++extern void efhw_handle_timeout_event(struct efhw_nic *,
++ struct efhw_ev_handler *,
++ efhw_event_t *);
++
++#endif /* __CI_EFHW_EVENTQ_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,81 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides some event-related macros. This file is designed for
++ * use from kernel and from the userland contexts.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EVENTQ_MACROS_H__
++#define __CI_EFHW_EVENTQ_MACROS_H__
++
++#include <ci/efhw/common.h>
++
++/*--------------------------------------------------------------------
++ *
++ * Event Queue manipulation
++ *
++ *--------------------------------------------------------------------*/
++
++#define EFHW_EVENT_OFFSET(q, s, i) \
++ (((s)->evq_ptr - (i) * (int32_t)sizeof(efhw_event_t)) \
++ & (q)->evq_mask)
++
++#define EFHW_EVENT_PTR(q, s, i) \
++ ((efhw_event_t *)((q)->evq_base + EFHW_EVENT_OFFSET(q, s, i)))
++
++#define EFHW_EVENTQ_NEXT(s) \
++ do { ((s)->evq_ptr += sizeof(efhw_event_t)); } while (0)
++
++#define EFHW_EVENTQ_PREV(s) \
++ do { ((s)->evq_ptr -= sizeof(efhw_event_t)); } while (0)
++
++/* Be worried about this on byteswapped machines */
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ /* Due to crazy chipsets, we see the event words being written in
++ ** arbitrary order (bug4539). So test for presence of event must ensure
++ ** that both halves have changed from the null.
++ */
++ #define EFHW_IS_EVENT(evp) \
++ (((evp)->opaque.a != (uint32_t)-1) && \
++ ((evp)->opaque.b != (uint32_t)-1))
++ #define EFHW_CLEAR_EVENT(evp) ((evp)->u64 = (uint64_t)-1)
++ #define EFHW_CLEAR_EVENT_VALUE 0xff
++#else
++ #error Fixme - unknown hardware configuration
++#endif
++
++#define EFHW_EVENT_OVERFLOW(evq, s) \
++ (EFHW_IS_EVENT(EFHW_EVENT_PTR(evq, s, 1)))
++
++#endif /* __CI_EFHW_EVENTQ_MACROS_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,93 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains API provided by efhw/falcon.c file. This file is not
++ * designed for use outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_FALCON_H__
++#define __CI_EFHW_FALCON_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efhw/common.h>
++
++/*----------------------------------------------------------------------------
++ *
++ * Locks - unfortunately required
++ *
++ *---------------------------------------------------------------------------*/
++
++#define FALCON_LOCK_DECL irq_flags_t lock_state
++#define FALCON_LOCK_LOCK(nic) \
++ spin_lock_irqsave((nic)->reg_lock, lock_state)
++#define FALCON_LOCK_UNLOCK(nic) \
++ spin_unlock_irqrestore((nic)->reg_lock, lock_state)
++
++extern struct efhw_func_ops falcon_char_functional_units;
++
++/*! specify a pace value for a TX DMA Queue */
++extern void falcon_nic_pace(struct efhw_nic *nic, uint dmaq, uint pace);
++
++/*! confirm buffer table updates - should be used for items where
++ loss of data would be unacceptable. E.g for the buffers that back
++ an event or DMA queue */
++extern void falcon_nic_buffer_table_confirm(struct efhw_nic *nic);
++
++/*! Reset the all the TX DMA queue pointers. */
++extern void falcon_clobber_tx_dma_ptrs(struct efhw_nic *nic, uint dmaq);
++
++extern int
++falcon_handle_char_event(struct efhw_nic *nic,
++ struct efhw_ev_handler *h, efhw_event_t *evp);
++
++/*! map event queue instance space (0,1,2,..) onto event queue
++ number. This function takes into account the allocation rules for
++ the underlying driver model */
++extern int falcon_idx_to_evq(struct efhw_nic *nic, uint idx);
++
++/*! Acknowledge to HW that processing is complete on a given event queue */
++extern void falcon_nic_evq_ack(struct efhw_nic *nic, uint evq, /* evq id */
++ uint rptr, /* new read pointer update */
++ bool wakeup /* request a wakeup event if
++ ptr's != */
++ );
++
++extern void
++falcon_nic_buffer_table_set_n(struct efhw_nic *nic, int buffer_id,
++ dma_addr_t dma_addr, uint bufsz, uint region,
++ int n_pages, int own_id);
++
++extern void falcon_nic_ipfilter_ctor(struct efhw_nic *nic);
++
++#endif /* __CI_EFHW_FALCON_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,58 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains API provided by efhw/falcon_hash.c file.
++ * Function declared in this file are not exported from the Linux
++ * sfc_resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_FALCON_HASH_H__
++#define __CI_EFHW_FALCON_HASH_H__
++
++/* All LE parameters */
++extern unsigned int
++falcon_hash_get_key(unsigned int src_ip, unsigned int src_port,
++ unsigned int dest_ip, unsigned int dest_port,
++ int tcp, int full);
++
++unsigned int falcon_hash_function1(unsigned int key, unsigned int nfilters);
++
++extern unsigned int
++falcon_hash_function2(unsigned int key, unsigned int nfitlers);
++
++extern unsigned int
++falcon_hash_iterator(unsigned int hash1, unsigned int hash2,
++ unsigned int n_search, unsigned int nfilters);
++
++#endif /* __CI_EFHW_FALCON_HASH_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,84 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for header files
++ * with hardware-related definitions (in ci/driver/efab/hardware*).
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_HARDWARE_LINUX_H__
++#define __CI_EFHW_HARDWARE_LINUX_H__
++
++#include <asm/io.h>
++
++#ifdef __LITTLE_ENDIAN
++#define EFHW_IS_LITTLE_ENDIAN
++#elif __BIG_ENDIAN
++#define EFHW_IS_BIG_ENDIAN
++#else
++#error Unknown endianness
++#endif
++
++#ifndef mmiowb
++ #if defined(__i386__) || defined(__x86_64__)
++ #define mmiowb()
++ #elif defined(__ia64__)
++ #ifndef ia64_mfa
++ #define ia64_mfa() asm volatile ("mf.a" ::: "memory")
++ #endif
++ #define mmiowb ia64_mfa
++ #else
++ #error "Need definition for mmiowb()"
++ #endif
++#endif
++
++typedef char *efhw_ioaddr_t;
++
++#ifndef readq
++static inline uint64_t __readq(void __iomem *addr)
++{
++ return *(volatile uint64_t *)addr;
++}
++#define readq(x) __readq(x)
++#endif
++
++#ifndef writeq
++static inline void __writeq(uint64_t v, void __iomem *addr)
++{
++ *(volatile uint64_t *)addr = v;
++}
++#define writeq(val, addr) __writeq((val), (addr))
++#endif
++
++#endif /* __CI_EFHW_HARDWARE_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,58 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains OS-independent API for allocating iopage types.
++ * The implementation of these functions is highly OS-dependent.
++ * This file is not designed for use outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_RESOURCE_IOPAGE_H__
++#define __CI_DRIVER_RESOURCE_IOPAGE_H__
++
++#include <ci/efhw/efhw_types.h>
++
++/*--------------------------------------------------------------------
++ *
++ * memory allocation
++ *
++ *--------------------------------------------------------------------*/
++
++extern int efhw_iopage_alloc(struct efhw_nic *, efhw_iopage_t *p);
++extern void efhw_iopage_free(struct efhw_nic *, efhw_iopage_t *p);
++
++extern int efhw_iopages_alloc(struct efhw_nic *, efhw_iopages_t *p,
++ unsigned order);
++extern void efhw_iopages_free(struct efhw_nic *, efhw_iopages_t *p);
++
++#endif /* __CI_DRIVER_RESOURCE_IOPAGE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,188 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides efhw_page_t and efhw_iopage_t for Linux kernel.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_IOPAGE_LINUX_H__
++#define __CI_EFHW_IOPAGE_LINUX_H__
++
++#include <linux/gfp.h>
++#include <linux/hardirq.h>
++#include <ci/efhw/debug.h>
++
++/*--------------------------------------------------------------------
++ *
++ * efhw_page_t: A single page of memory. Directly mapped in the driver,
++ * and can be mapped to userlevel.
++ *
++ *--------------------------------------------------------------------*/
++
++typedef struct {
++ unsigned long kva;
++} efhw_page_t;
++
++static inline int efhw_page_alloc(efhw_page_t *p)
++{
++ p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
++ return p->kva ? 0 : -ENOMEM;
++}
++
++static inline int efhw_page_alloc_zeroed(efhw_page_t *p)
++{
++ p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
++ return p->kva ? 0 : -ENOMEM;
++}
++
++static inline void efhw_page_free(efhw_page_t *p)
++{
++ free_page(p->kva);
++ EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
++}
++
++static inline char *efhw_page_ptr(efhw_page_t *p)
++{
++ return (char *)p->kva;
++}
++
++static inline unsigned efhw_page_pfn(efhw_page_t *p)
++{
++ return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
++}
++
++static inline void efhw_page_mark_invalid(efhw_page_t *p)
++{
++ p->kva = 0;
++}
++
++static inline int efhw_page_is_valid(efhw_page_t *p)
++{
++ return p->kva != 0;
++}
++
++static inline void efhw_page_init_from_va(efhw_page_t *p, void *va)
++{
++ p->kva = (unsigned long)va;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * efhw_iopage_t: A single page of memory. Directly mapped in the driver,
++ * and can be mapped to userlevel. Can also be accessed by the NIC.
++ *
++ *--------------------------------------------------------------------*/
++
++typedef struct {
++ efhw_page_t p;
++ dma_addr_t dma_addr;
++} efhw_iopage_t;
++
++static inline dma_addr_t efhw_iopage_dma_addr(efhw_iopage_t *p)
++{
++ return p->dma_addr;
++}
++
++#define efhw_iopage_ptr(iop) efhw_page_ptr(&(iop)->p)
++#define efhw_iopage_pfn(iop) efhw_page_pfn(&(iop)->p)
++#define efhw_iopage_mark_invalid(iop) efhw_page_mark_invalid(&(iop)->p)
++#define efhw_iopage_is_valid(iop) efhw_page_is_valid(&(iop)->p)
++
++/*--------------------------------------------------------------------
++ *
++ * efhw_iopages_t: A set of pages that are contiguous in physical memory.
++ * Directly mapped in the driver, and can be mapped to userlevel. Can also
++ * be accessed by the NIC.
++ *
++ * NB. The O/S may be unwilling to allocate many, or even any of these. So
++ * only use this type where the NIC really needs a physically contiguous
++ * buffer.
++ *
++ *--------------------------------------------------------------------*/
++
++typedef struct {
++ caddr_t kva;
++ unsigned order;
++ dma_addr_t dma_addr;
++} efhw_iopages_t;
++
++static inline caddr_t efhw_iopages_ptr(efhw_iopages_t *p)
++{
++ return p->kva;
++}
++
++static inline unsigned efhw_iopages_pfn(efhw_iopages_t *p)
++{
++ return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
++}
++
++static inline dma_addr_t efhw_iopages_dma_addr(efhw_iopages_t *p)
++{
++ return p->dma_addr;
++}
++
++static inline unsigned efhw_iopages_size(efhw_iopages_t *p)
++{
++ return 1u << (p->order + PAGE_SHIFT);
++}
++
++/* efhw_iopage_t <-> efhw_iopages_t conversions for handling physically
++ * contiguous allocations in iobufsets for iSCSI. This allows the
++ * essential information about contiguous allocations from
++ * efhw_iopages_alloc() to be saved away in the efhw_iopage_t array in an
++ * iobufset. (Changing the iobufset resource to use a union type would
++ * involve a lot of code changes, and make the iobufset's metadata larger
++ * which could be bad as it's supposed to fit into a single page on some
++ * platforms.)
++ */
++static inline void
++efhw_iopage_init_from_iopages(efhw_iopage_t *iopage,
++ efhw_iopages_t *iopages, unsigned pageno)
++{
++ iopage->p.kva = ((unsigned long)efhw_iopages_ptr(iopages))
++ + (pageno * PAGE_SIZE);
++ iopage->dma_addr = efhw_iopages_dma_addr(iopages) +
++ (pageno * PAGE_SIZE);
++}
++
++static inline void
++efhw_iopages_init_from_iopage(efhw_iopages_t *iopages,
++ efhw_iopage_t *iopage, unsigned order)
++{
++ iopages->kva = (caddr_t) efhw_iopage_ptr(iopage);
++ EFHW_ASSERT(iopages->kva);
++ iopages->order = order;
++ iopages->dma_addr = efhw_iopage_dma_addr(iopage);
++}
++
++#endif /* __CI_EFHW_IOPAGE_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/nic.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/nic.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/nic.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/nic.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,62 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains API provided by efhw/nic.c file. This file is not
++ * designed for use outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_NIC_H__
++#define __CI_EFHW_NIC_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efhw/public.h>
++
++
++/* Convert PCI info to device type. Returns false when device is not
++ * recognised.
++ */
++extern int efhw_device_type_init(struct efhw_device_type *dt,
++ int vendor_id, int device_id, int revision);
++
++/* Initialise fields that do not involve touching hardware. */
++extern void efhw_nic_init(struct efhw_nic *nic, unsigned flags,
++ unsigned options, struct efhw_device_type dev_type);
++
++/*! Destruct NIC resources */
++extern void efhw_nic_dtor(struct efhw_nic *nic);
++
++/*! Shutdown interrupts */
++extern void efhw_nic_close_interrupts(struct efhw_nic *nic);
++
++#endif /* __CI_EFHW_NIC_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/public.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/public.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/public.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/public.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,83 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API of efhw library exported from the SFC
++ * resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_PUBLIC_H__
++#define __CI_EFHW_PUBLIC_H__
++
++#include <ci/efhw/common.h>
++#include <ci/efhw/efhw_types.h>
++
++/*! Returns true if we have some EtherFabric functional units -
++ whether configured or not */
++static inline int efhw_nic_have_functional_units(struct efhw_nic *nic)
++{
++ return nic->efhw_func != 0;
++}
++
++/*! Returns true if the EtherFabric functional units have been configured */
++static inline int efhw_nic_have_hw(struct efhw_nic *nic)
++{
++ return efhw_nic_have_functional_units(nic) && (EFHW_KVA(nic) != 0);
++}
++
++/*! Helper function to allocate the iobuffer needed by an eventq
++ * - it ensures the eventq has the correct alignment for the NIC
++ *
++ * \param rm Event-queue resource manager
++ * \param instance Event-queue instance (index)
++ * \param buf_bytes Requested size of eventq
++ * \return < 0 if iobuffer allocation fails
++ */
++int efhw_nic_event_queue_alloc_iobuffer(struct efhw_nic *nic,
++ struct eventq_resource_hardware *h,
++ int evq_instance, unsigned buf_bytes);
++
++extern void falcon_nic_set_rx_usr_buf_size(struct efhw_nic *,
++ int rx_usr_buf_size);
++
++extern void
++falcon_nic_rx_filter_ctl_set(struct efhw_nic *nic, uint32_t tcp_full,
++ uint32_t tcp_wild,
++ uint32_t udp_full, uint32_t udp_wild);
++
++extern void
++falcon_nic_rx_filter_ctl_get(struct efhw_nic *nic, uint32_t *tcp_full,
++ uint32_t *tcp_wild,
++ uint32_t *udp_full, uint32_t *udp_wild);
++
++#endif /* __CI_EFHW_PUBLIC_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,72 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for efhw library.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_SYSDEP_LINUX_H__
++#define __CI_EFHW_SYSDEP_LINUX_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++#include <linux/if_ether.h>
++
++#include <linux/netdevice.h> /* necessary for etherdevice.h on some kernels */
++#include <linux/etherdevice.h>
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)
++static inline int is_local_ether_addr(const u8 *addr)
++{
++ return (0x02 & addr[0]);
++}
++#endif
++
++typedef unsigned long irq_flags_t;
++
++#define spin_lock_destroy(l_) do {} while (0)
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#define HAS_NET_NAMESPACE
++#endif
++
++/* Funny, but linux has round_up for x86 only, defined in
++ * x86-specific header */
++#ifndef round_up
++#define round_up(x, y) (((x) + (y) - 1) & ~((y)-1))
++#endif
++
++#endif /* __CI_EFHW_SYSDEP_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,69 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides private API for buddy allocator. This API is not
++ * designed for use outside of SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_BUDDY_H__
++#define __CI_EFRM_BUDDY_H__
++
++#include <ci/efrm/sysdep.h>
++
++/*! Comment? */
++struct efrm_buddy_allocator {
++ struct list_head *free_lists; /* array[order+1] */
++ struct list_head *links; /* array[1<<order] */
++ uint8_t *orders; /* array[1<<order] */
++ unsigned order; /*!< total size == (1 << order) */
++ /* ?? Consider recording largest available order + for each order the
++ ** smallest available order that is big enough.
++ */
++};
++
++ /*! Returns total size of managed space. */
++static inline unsigned long efrm_buddy_size(struct efrm_buddy_allocator *b)
++{
++ return 1ul << b->order;
++}
++
++int efrm_buddy_ctor(struct efrm_buddy_allocator *b, unsigned order);
++void efrm_buddy_dtor(struct efrm_buddy_allocator *b);
++int efrm_buddy_alloc(struct efrm_buddy_allocator *b, unsigned order);
++void efrm_buddy_free(struct efrm_buddy_allocator *b, unsigned addr,
++ unsigned order);
++void efrm_buddy_reserve_at_start(struct efrm_buddy_allocator *b, unsigned n);
++void efrm_buddy_reserve_at_end(struct efrm_buddy_allocator *b, unsigned n);
++
++#endif /* __CI_EFRM_BUDDY_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,86 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides private buffer table API. This API is not designed
++ * for use outside of SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_BUFFER_TABLE_H__
++#define __CI_EFRM_BUFFER_TABLE_H__
++
++#include <ci/efhw/efhw_types.h>
++
++/*--------------------------------------------------------------------
++ *
++ * NIC's buffer table.
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Managed interface. */
++
++/*! construct a managed buffer table object, allocated over a region of
++ * the NICs buffer table space
++ */
++extern int efrm_buffer_table_ctor(unsigned low, unsigned high);
++/*! destructor for above */
++extern void efrm_buffer_table_dtor(void);
++
++/*! allocate a contiguous region of buffer table space */
++extern int efrm_buffer_table_alloc(unsigned order,
++ struct efhw_buffer_table_allocation *a);
++
++/*! current size of the buffer table.
++ * FIXME This function should be inline, but it is never used from
++ * the fast path, so let it as-is. */
++unsigned long efrm_buffer_table_size(void);
++
++/*--------------------------------------------------------------------
++ *
++ * buffer table operations through the HW independent API
++ *
++ *--------------------------------------------------------------------*/
++
++/*! free a previously allocated region of buffer table space */
++extern void efrm_buffer_table_free(struct efhw_buffer_table_allocation *a);
++
++/*! commit the update of a buffer table entry to every NIC */
++void efrm_buffer_table_commit(void);
++
++/*! set a given buffer table entry. [pa] should be the physical
++ address of pinned down memory. This function can only be called from
++ the char driver */
++void efrm_buffer_table_set(struct efhw_buffer_table_allocation *a,
++ unsigned i, dma_addr_t dma_addr, int owner);
++
++#endif /* __CI_EFRM_BUFFER_TABLE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/debug.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/debug.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/debug.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,78 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides debug-related API for efrm library using Linux kernel
++ * primitives.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_DEBUG_LINUX_H__
++#define __CI_EFRM_DEBUG_LINUX_H__
++
++#define EFRM_PRINTK_PREFIX "[sfc efrm] "
++
++#define EFRM_PRINTK(level, fmt, ...) \
++ printk(level EFRM_PRINTK_PREFIX fmt "\n", __VA_ARGS__)
++
++/* Following macros should be used with non-zero format parameters
++ * due to __VA_ARGS__ limitations. Use "%s" with __FUNCTION__ if you can't
++ * find better parameters. */
++#define EFRM_ERR(fmt, ...) EFRM_PRINTK(KERN_ERR, fmt, __VA_ARGS__)
++#define EFRM_WARN(fmt, ...) EFRM_PRINTK(KERN_WARNING, fmt, __VA_ARGS__)
++#define EFRM_NOTICE(fmt, ...) EFRM_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__)
++#if 0 && !defined(NDEBUG)
++#define EFRM_TRACE(fmt, ...) EFRM_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__)
++#else
++#define EFRM_TRACE(fmt, ...)
++#endif
++
++#ifndef NDEBUG
++#define EFRM_ASSERT(cond) BUG_ON((cond) == 0)
++#define _EFRM_ASSERT(cond, file, line) \
++ do { \
++ if (unlikely(!(cond))) { \
++ EFRM_ERR("assertion \"%s\" failed at %s %d", \
++ #cond, file, line); \
++ BUG(); \
++ } \
++ } while (0)
++
++#define EFRM_DO_DEBUG(expr) expr
++#define EFRM_VERIFY_EQ(expr, val) EFRM_ASSERT((expr) == (val))
++#else
++#define EFRM_ASSERT(cond)
++#define EFRM_DO_DEBUG(expr)
++#define EFRM_VERIFY_EQ(expr, val) expr
++#endif
++
++#endif /* __CI_EFRM_DEBUG_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,86 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides private API of efrm library to be used from the SFC
++ * resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_DRIVER_PRIVATE_H__
++#define __CI_EFRM_DRIVER_PRIVATE_H__
++
++#include <ci/efrm/resource.h>
++#include <ci/efrm/sysdep.h>
++
++/*--------------------------------------------------------------------
++ *
++ * global variables
++ *
++ *--------------------------------------------------------------------*/
++
++/* Internal structure for resource driver */
++extern struct efrm_resource_manager *efrm_rm_table[];
++
++/*--------------------------------------------------------------------
++ *
++ * efrm_nic_table handling
++ *
++ *--------------------------------------------------------------------*/
++
++extern int efrm_driver_ctor(void);
++extern int efrm_driver_dtor(void);
++extern int efrm_driver_register_nic(struct efhw_nic *, int nic_index);
++extern int efrm_driver_unregister_nic(struct efhw_nic *);
++
++/*--------------------------------------------------------------------
++ *
++ * create/destroy resource managers
++ *
++ *--------------------------------------------------------------------*/
++
++struct vi_resource_dimensions {
++ unsigned evq_int_min, evq_int_max;
++ unsigned evq_timer_min, evq_timer_max;
++ unsigned rxq_min, rxq_max;
++ unsigned txq_min, txq_max;
++};
++
++/*! Initialise resources */
++extern int
++efrm_resources_init(const struct vi_resource_dimensions *,
++ int buffer_table_min, int buffer_table_max);
++
++/*! Tear down resources */
++extern void efrm_resources_fini(void);
++
++#endif /* __CI_EFRM_DRIVER_PRIVATE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/filter.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/filter.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/filter.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/filter.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,147 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for filter resource.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_FILTER_H__
++#define __CI_EFRM_FILTER_H__
++
++#include <ci/efrm/resource.h>
++#include <ci/efrm/vi_resource.h>
++#include <ci/efrm/nic_set.h>
++#include <ci/efhw/common.h>
++
++/*! Comment? */
++struct filter_resource {
++ struct efrm_resource rs;
++ struct vi_resource *pt;
++ int filter_idx;
++ efrm_nic_set_t nic_set;
++};
++
++#define filter_resource(rs1) container_of((rs1), struct filter_resource, rs)
++
++/*!
++ * Allocate filter resource.
++ *
++ * \param vi_parent VI resource to use as parent. The function takes
++ * reference to the VI resource on success.
++ * \param frs_out pointer to return the new filter resource
++ *
++ * \return status code; if non-zero, frs_out is unchanged
++ */
++extern int
++efrm_filter_resource_alloc(struct vi_resource *vi_parent,
++ struct filter_resource **frs_out);
++
++/* efrm_filter_resource_free should be called only if
++ * __efrm_resource_ref_count_zero() returned true.
++ * The easiest way is to call efrm_filter_resource_release() */
++void efrm_filter_resource_free(struct filter_resource *frs);
++static inline void efrm_filter_resource_release(struct filter_resource *frs)
++{
++ unsigned id;
++
++ EFRM_RESOURCE_ASSERT_VALID(&frs->rs, 0);
++ id = EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle);
++
++ if (atomic_dec_and_test(&frs->rs.rs_ref_count)) {
++ if (__efrm_resource_ref_count_zero(EFRM_RESOURCE_FILTER, id)) {
++ EFRM_ASSERT(EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle) ==
++ id);
++ efrm_filter_resource_free(frs);
++ }
++ }
++}
++
++/*--------------------------------------------------------------------
++ *!
++ * Called to set/change the PT endpoint of a filter
++ *
++ * Example of use is TCP helper when it finds a wildcard IP filter
++ * needs to change which application it delivers traffic to
++ *
++ * \param frs filter resource
++ * \param pt_handle handle of new PT endpoint
++ *
++ * \return standard error codes
++ *
++ *--------------------------------------------------------------------*/
++extern int
++efrm_filter_resource_set_ptresource(struct filter_resource *frs,
++ struct vi_resource *virs);
++
++extern int efrm_filter_resource_clear(struct filter_resource *frs);
++
++extern int __efrm_filter_resource_set(struct filter_resource *frs, int type,
++ unsigned saddr_be32, uint16_t sport_be16,
++ unsigned daddr_be32, uint16_t dport_be16);
++
++static inline int
++efrm_filter_resource_tcp_set(struct filter_resource *frs,
++ unsigned saddr, uint16_t sport,
++ unsigned daddr, uint16_t dport)
++{
++ int type;
++
++ EFRM_ASSERT((saddr && sport) || (!saddr && !sport));
++
++ type =
++ saddr ? EFHW_IP_FILTER_TYPE_TCP_FULL :
++ EFHW_IP_FILTER_TYPE_TCP_WILDCARD;
++
++ return __efrm_filter_resource_set(frs, type,
++ saddr, sport, daddr, dport);
++}
++
++static inline int
++efrm_filter_resource_udp_set(struct filter_resource *frs,
++ unsigned saddr, uint16_t sport,
++ unsigned daddr, uint16_t dport)
++{
++ int type;
++
++ EFRM_ASSERT((saddr && sport) || (!saddr && !sport));
++
++ type =
++ saddr ? EFHW_IP_FILTER_TYPE_UDP_FULL :
++ EFHW_IP_FILTER_TYPE_UDP_WILDCARD;
++
++ return __efrm_filter_resource_set(frs,
++ type, saddr, sport, daddr, dport);
++}
++
++#endif /* __CI_EFRM_FILTER_H__ */
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,123 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for iobufset resource.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_IOBUFSET_H__
++#define __CI_EFRM_IOBUFSET_H__
++
++#include <ci/efrm/vi_resource.h>
++
++/*! Iobufset resource structture.
++ * Users should not access the structure fields directly, but use the API
++ * below.
++ * However, this structure should not be moved out of public headers,
++ * because part of API (ex. efrm_iobufset_dma_addr function) is inline and
++ * is used in the fast-path code.
++ */
++struct iobufset_resource {
++ struct efrm_resource rs;
++ struct vi_resource *evq;
++ struct efhw_buffer_table_allocation buf_tbl_alloc;
++ unsigned int faultonaccess;
++ unsigned int n_bufs;
++ unsigned int pages_per_contiguous_chunk;
++ unsigned order;
++ efhw_iopage_t bufs[1];
++ /*!< up to n_bufs can follow this, so this must be the last member */
++};
++
++#define iobufset_resource(rs1) \
++ container_of((rs1), struct iobufset_resource, rs)
++
++/*!
++ * Allocate iobufset resource.
++ *
++ * \param vi_evq VI resource to use. The function takes
++ * reference to the VI resource on success.
++ * \param iobrs_out pointer to return the new filter resource
++ *
++ * \return status code; if non-zero, frs_out is unchanged
++ */
++extern int
++efrm_iobufset_resource_alloc(int32_t n_pages,
++ int32_t pages_per_contiguous_chunk,
++ struct vi_resource *vi_evq,
++ bool phys_addr_mode,
++ uint32_t faultonaccess,
++ struct iobufset_resource **iobrs_out);
++
++/* efrm_iobufset_resource_free should be called only if
++ * __efrm_resource_ref_count_zero() returned true.
++ * The easiest way is to call efrm_iobufset_resource_release() */
++void efrm_iobufset_resource_free(struct iobufset_resource *rs);
++static inline void
++efrm_iobufset_resource_release(struct iobufset_resource *iobrs)
++{
++ unsigned id;
++
++ EFRM_RESOURCE_ASSERT_VALID(&iobrs->rs, 0);
++ id = EFRM_RESOURCE_INSTANCE(iobrs->rs.rs_handle);
++
++ if (atomic_dec_and_test(&iobrs->rs.rs_ref_count)) {
++ if (__efrm_resource_ref_count_zero(EFRM_RESOURCE_IOBUFSET, id))
++ efrm_iobufset_resource_free(iobrs);
++ }
++}
++
++static inline char *
++efrm_iobufset_ptr(struct iobufset_resource *rs, unsigned offs)
++{
++ EFRM_ASSERT(offs < (unsigned)(rs->n_bufs << PAGE_SHIFT));
++ return efhw_iopage_ptr(&rs->bufs[offs >> PAGE_SHIFT])
++ + (offs & (PAGE_SIZE - 1));
++}
++
++static inline char *efrm_iobufset_page_ptr(struct iobufset_resource *rs,
++ unsigned page_i)
++{
++ EFRM_ASSERT(page_i < (unsigned)rs->n_bufs);
++ return efhw_iopage_ptr(&rs->bufs[page_i]);
++}
++
++static inline dma_addr_t
++efrm_iobufset_dma_addr(struct iobufset_resource *rs, unsigned offs)
++{
++ EFRM_ASSERT(offs < (unsigned)(rs->n_bufs << PAGE_SHIFT));
++ return efhw_iopage_dma_addr(&rs->bufs[offs >> PAGE_SHIFT])
++ + (offs & (PAGE_SIZE - 1));
++}
++
++#endif /* __CI_EFRM_IOBUFSET_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,104 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for NIC sets.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_NIC_SET_H__
++#define __CI_EFRM_NIC_SET_H__
++
++#include <ci/efrm/debug.h>
++#include <ci/efhw/common_sysdep.h>
++#include <ci/efhw/efhw_config.h>
++
++/*--------------------------------------------------------------------
++ *
++ * efrm_nic_set_t - tracks which NICs something has been done on
++ *
++ *--------------------------------------------------------------------*/
++
++/* Internal suructure of efrm_nic_set_t should not be referenced outside of
++ * this file. Add a new accessor if you should do it. */
++typedef struct {
++ uint32_t nics;
++} efrm_nic_set_t;
++
++#if EFHW_MAX_NR_DEVS > 32
++#error change efrm_nic_set to handle EFHW_MAX_NR_DEVS number of devices
++#endif
++
++static inline bool
++efrm_nic_set_read(const efrm_nic_set_t *nic_set, unsigned index)
++{
++ EFRM_ASSERT(nic_set);
++ EFRM_ASSERT(index < EFHW_MAX_NR_DEVS && index < 32);
++ return (nic_set->nics & (1 << index)) ? true : false;
++}
++
++static inline void
++efrm_nic_set_write(efrm_nic_set_t *nic_set, unsigned index, bool value)
++{
++ EFRM_ASSERT(nic_set);
++ EFRM_ASSERT(index < EFHW_MAX_NR_DEVS && index < 32);
++ EFRM_ASSERT(value == false || value == true);
++ nic_set->nics = (nic_set->nics & (~(1 << index))) + (value << index);
++}
++
++static inline void efrm_nic_set_clear(efrm_nic_set_t *nic_set)
++{
++ nic_set->nics = 0;
++}
++
++static inline void efrm_nic_set_all(efrm_nic_set_t *nic_set)
++{
++ nic_set->nics = 0xffffffff;
++}
++
++static inline bool efrm_nic_set_is_all_clear(efrm_nic_set_t *nic_set)
++{
++ return nic_set->nics == 0 ? true : false;
++}
++
++#define EFRM_NIC_SET_FMT "%x"
++
++static inline uint32_t efrm_nic_set_pri_arg(efrm_nic_set_t *nic_set)
++{
++ return nic_set->nics;
++}
++
++#define EFRM_FOR_EACH_NIC_INDEX_IN_SET(_set, _nic_i) \
++ for ((_nic_i) = 0; (_nic_i) < EFHW_MAX_NR_DEVS; ++(_nic_i)) \
++ if (efrm_nic_set_read((_set), (_nic_i)))
++
++#endif /* __CI_EFRM_NIC_SET_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,98 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for NIC table.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_NIC_TABLE_H__
++#define __CI_EFRM_NIC_TABLE_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efrm/sysdep.h>
++
++/*--------------------------------------------------------------------
++ *
++ * struct efrm_nic_table - top level driver object keeping all NICs -
++ * implemented in driver_object.c
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Comment? */
++struct efrm_nic_table {
++ /*! nics attached to this driver */
++ struct efhw_nic *nic[EFHW_MAX_NR_DEVS];
++ /*! pointer to an arbitrary struct efhw_nic if one exists;
++ * for code which does not care which NIC it wants but
++ * still needs one. Note you cannot assume nic[0] exists. */
++ struct efhw_nic *a_nic;
++ uint32_t nic_count; /*!< number of nics attached to this driver */
++ spinlock_t lock; /*!< lock for table modifications */
++ atomic_t ref_count; /*!< refcount for users of nic table */
++};
++
++/* Resource driver structures used by other drivers as well */
++extern struct efrm_nic_table efrm_nic_table;
++
++static inline void efrm_nic_table_hold(void)
++{
++ atomic_inc(&efrm_nic_table.ref_count);
++}
++
++static inline void efrm_nic_table_rele(void)
++{
++ atomic_dec(&efrm_nic_table.ref_count);
++}
++
++static inline int efrm_nic_table_held(void)
++{
++ return (atomic_read(&efrm_nic_table.ref_count) != 0);
++}
++
++/* Run code block _x multiple times with variable nic set to each
++ * registered NIC in turn.
++ * DO NOT "break" out of this loop early. */
++#define EFRM_FOR_EACH_NIC(_nic_i, _nic) \
++ for ((_nic_i) = (efrm_nic_table_hold(), 0); \
++ (_nic_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \
++ (_nic_i)++) \
++ if (((_nic) = efrm_nic_table.nic[_nic_i]))
++
++#define EFRM_FOR_EACH_NIC_IN_SET(_set, _i, _nic) \
++ for ((_i) = (efrm_nic_table_hold(), 0); \
++ (_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \
++ ++(_i)) \
++ if (((_nic) = efrm_nic_table.nic[_i]) && \
++ efrm_nic_set_read((_set), (_i)))
++
++#endif /* __CI_EFRM_NIC_TABLE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/private.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/private.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/private.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/private.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,141 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides private API of efrm library -- resource handling.
++ * This API is not designed for use outside of SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_PRIVATE_H__
++#define __CI_EFRM_PRIVATE_H__
++
++#include <ci/efrm/resource.h>
++#include <ci/efrm/driver_private.h>
++#include <ci/efrm/sysdep.h>
++#include <ci/efrm/debug.h>
++
++/*--------------------------------------------------------------------
++ *
++ * create resource managers
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Create a resource manager for various types of resources
++ */
++extern int
++efrm_create_iobufset_resource_manager(struct efrm_resource_manager **out);
++
++extern int
++efrm_create_filter_resource_manager(struct efrm_resource_manager **out);
++
++extern int
++efrm_create_vi_resource_manager(struct efrm_resource_manager **out,
++ const struct vi_resource_dimensions *);
++
++/*--------------------------------------------------------------------
++ *
++ * efrm_resource_handle_t handling
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Initialize an area of memory to be used as a resource */
++static inline void efrm_resource_init(struct efrm_resource *rs,
++ int type, int instance)
++{
++ EFRM_ASSERT(instance >= 0);
++ EFRM_ASSERT(type >= 0 && type < EFRM_RESOURCE_NUM);
++ atomic_set(&rs->rs_ref_count, 1);
++ rs->rs_handle.handle = (type << 28u) |
++ (((unsigned)jiffies & 0xfff) << 16) | instance;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Instance pool management
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Allocate instance pool. Use kfifo_vfree to destroy it. */
++static inline int
++efrm_kfifo_id_ctor(struct kfifo **ids_out,
++ unsigned int base, unsigned int limit, spinlock_t *lock)
++{
++ unsigned int i;
++ struct kfifo *ids;
++ unsigned char *buffer;
++ unsigned int size = roundup_pow_of_two((limit - base) * sizeof(int));
++
++ EFRM_ASSERT(base <= limit);
++ buffer = vmalloc(size);
++ ids = kfifo_init(buffer, size, GFP_KERNEL, lock);
++ if (IS_ERR(ids))
++ return PTR_ERR(ids);
++ for (i = base; i < limit; i++)
++ EFRM_VERIFY_EQ(__kfifo_put(ids, (unsigned char *)&i,
++ sizeof(i)), sizeof(i));
++
++ *ids_out = ids;
++ return 0;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Various private functions
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Initialize the fields in the provided resource manager memory area
++ * \param rm The area of memory to be initialized
++ * \param dtor A method to destroy the resource manager
++ * \param name A Textual name for the resource manager
++ * \param type The type of resource managed
++ * \param initial_table_size Initial size of the ID table
++ * \param auto_destroy Destroy resource manager on driver onload iff true
++ *
++ * A default table size is provided if the value 0 is provided.
++ */
++extern int
++efrm_resource_manager_ctor(struct efrm_resource_manager *rm,
++ void (*dtor)(struct efrm_resource_manager *),
++ const char *name, unsigned type,
++ int initial_table_size);
++
++extern void efrm_resource_manager_dtor(struct efrm_resource_manager *rm);
++
++/*! Insert a resource into table in the resource manager.
++ *
++ * Caller should free the resource if this function returns non-zero.
++ */
++extern int efrm_resource_manager_insert(struct efrm_resource *rs);
++
++#endif /* __CI_EFRM_PRIVATE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/resource.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/resource.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/resource.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/resource.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,122 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public interface of efrm library -- resource handling.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_RESOURCE_H__
++#define __CI_EFRM_RESOURCE_H__
++
++/*--------------------------------------------------------------------
++ *
++ * headers for type dependencies
++ *
++ *--------------------------------------------------------------------*/
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efrm/resource_id.h>
++#include <ci/efrm/sysdep.h>
++#include <ci/efhw/common_sysdep.h>
++
++#ifndef __ci_driver__
++#error "Driver-only file"
++#endif
++
++/*--------------------------------------------------------------------
++ *
++ * struct efrm_resource - represents an allocated resource
++ * (eg. pinned pages of memory, or resource on a NIC)
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Representation of an allocated resource */
++struct efrm_resource {
++ atomic_t rs_ref_count; /*!< users count; see
++ * __efrm_resource_ref_count_zero() */
++ efrm_resource_handle_t rs_handle;
++};
++
++/*--------------------------------------------------------------------
++ *
++ * managed resource abstraction
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Factory for resources of a specific type */
++struct efrm_resource_manager {
++ const char *rm_name; /*!< human readable only */
++ spinlock_t rm_lock;
++#ifndef NDEBUG
++ unsigned rm_type;
++#endif
++ int rm_resources;
++ int rm_resources_hiwat;
++ /*! table of allocated resources */
++ struct efrm_resource **rm_table;
++ unsigned rm_table_size;
++ /**
++ * Destructor for the resource manager. Other resource managers
++ * might be already dead, although the system guarantees that
++ * managers are destructed in the order by which they were created
++ */
++ void (*rm_dtor)(struct efrm_resource_manager *);
++};
++
++#ifdef NDEBUG
++# define EFRM_RESOURCE_ASSERT_VALID(rs, rc_mbz)
++# define EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm)
++#else
++/*! Check validity of resource and report on failure */
++extern void efrm_resource_assert_valid(struct efrm_resource *,
++ int rc_may_be_zero,
++ const char *file, int line);
++# define EFRM_RESOURCE_ASSERT_VALID(rs, rc_mbz) \
++ efrm_resource_assert_valid((rs), (rc_mbz), __FILE__, __LINE__)
++
++/*! Check validity of resource manager and report on failure */
++extern void efrm_resource_manager_assert_valid(struct efrm_resource_manager *,
++ const char *file, int line);
++# define EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm) \
++ efrm_resource_manager_assert_valid((rm), __FILE__, __LINE__)
++#endif
++
++/*! Check the reference count on the resource provided and delete its
++ * handle it in its owning resource manager if the
++ * reference count has fallen to zero.
++ *
++ * Returns TRUE if the caller should really free the resource.
++ */
++extern bool __efrm_resource_ref_count_zero(unsigned type, unsigned instance);
++
++#endif /* __CI_EFRM_RESOURCE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,104 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public type and definitions resource handle, and the
++ * definitions of resource types.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFRM_RESOURCE_ID_H__
++#define __CI_DRIVER_EFRM_RESOURCE_ID_H__
++
++/***********************************************************************
++ * Resource handles
++ *
++ * Resource handles are intended for identifying resources at kernel
++ * level, within the context of a particular NIC. particularly because
++ * for some resource types, the low 16 bites correspond to hardware
++ * IDs. They were historically also used at user level, with a nonce
++ * stored in the bits 16 to 27 (inclusive), but that approach is
++ * deprecated (but sill alive!).
++ *
++ * The handle value 0 is used to mean "no resource".
++ * Identify resources within the context of a file descriptor at user
++ * level.
++ ***********************************************************************/
++
++typedef struct efrm_resource_handle_s {
++ uint32_t handle;
++} efrm_resource_handle_t;
++
++/* You may think these following functions should all have
++ * _HANDLE_ in their names, but really we are providing an abstract set
++ * of methods on a (hypothetical) efrm_resource_t object, with
++ * efrm_resource_handle_t being just the reference one holds to access
++ * the object (aka "this" or "self").
++ */
++
++/* Below I use inline instead of macros where possible in order to get
++ * more type checking help from the compiler; hopefully we'll never
++ * have to rewrite these to use #define as we've found some horrible
++ * compiler on which we cannot make static inline do the Right Thing (tm).
++ *
++ * For consistency and to avoid pointless change I spell these
++ * routines as macro names (CAPTILIZE_UNDERSCORED), which also serves
++ * to remind people they are compact and inlined.
++ */
++
++#define EFRM_RESOURCE_FMT "[rs:%08x]"
++
++static inline unsigned EFRM_RESOURCE_PRI_ARG(efrm_resource_handle_t h)
++{
++ return (h.handle);
++}
++
++static inline unsigned EFRM_RESOURCE_INSTANCE(efrm_resource_handle_t h)
++{
++ return (h.handle & 0x0000ffff);
++}
++
++static inline unsigned EFRM_RESOURCE_TYPE(efrm_resource_handle_t h)
++{
++ return (h.handle & 0xf0000000) >> 28;
++}
++
++/***********************************************************************
++ * Resource type codes
++ ***********************************************************************/
++
++#define EFRM_RESOURCE_IOBUFSET 0x0
++#define EFRM_RESOURCE_VI 0x1
++#define EFRM_RESOURCE_FILTER 0x2
++#define EFRM_RESOURCE_NUM 0x3 /* This isn't a resource! */
++
++#define EFRM_RESOURCE_NAME(type) \
++ ((type) == EFRM_RESOURCE_IOBUFSET? "IOBUFSET" : \
++ (type) == EFRM_RESOURCE_VI? "VI" : \
++ (type) == EFRM_RESOURCE_FILTER? "FILTER" : \
++ "<invalid>")
++
++#endif /* __CI_DRIVER_EFRM_RESOURCE_ID_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,54 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides Linux-like system-independent API for efrm library.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_SYSDEP_H__
++#define __CI_EFRM_SYSDEP_H__
++
++/* Spinlocks are defined in efhw/sysdep.h */
++#include <ci/efhw/sysdep.h>
++
++#if defined(__linux__) && defined(__KERNEL__)
++
++# include <ci/efrm/sysdep_linux.h>
++
++#else
++
++# include <ci/efrm/sysdep_ci2linux.h>
++
++#endif
++
++#endif /* __CI_EFRM_SYSDEP_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,248 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for efrm library.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Kfifo API is partially stolen from linux-2.6.22/include/linux/list.h
++ * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_SYSDEP_LINUX_H__
++#define __CI_EFRM_SYSDEP_LINUX_H__
++
++#include <linux/version.h>
++#include <linux/list.h>
++#include <linux/vmalloc.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/workqueue.h>
++#include <linux/gfp.h>
++#include <linux/slab.h>
++#include <linux/hardirq.h>
++#include <linux/kernel.h>
++#include <linux/if_ether.h>
++#include <linux/completion.h>
++#include <linux/in.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++/* get roundup_pow_of_two(), which was in kernel.h in early kernel versions */
++#include <linux/log2.h>
++#endif
++
++/********************************************************************
++ *
++ * List API
++ *
++ ********************************************************************/
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++static inline void
++list_replace_init(struct list_head *old, struct list_head *new)
++{
++ new->next = old->next;
++ new->next->prev = new;
++ new->prev = old->prev;
++ new->prev->next = new;
++ INIT_LIST_HEAD(old);
++}
++#endif
++
++static inline struct list_head *list_pop(struct list_head *list)
++{
++ struct list_head *link = list->next;
++ list_del(link);
++ return link;
++}
++
++static inline struct list_head *list_pop_tail(struct list_head *list)
++{
++ struct list_head *link = list->prev;
++ list_del(link);
++ return link;
++}
++
++/********************************************************************
++ *
++ * Workqueue API
++ *
++ ********************************************************************/
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++#define NEED_OLD_WORK_API
++
++/**
++ * The old and new work function prototypes just change
++ * the type of the pointer in the only argument, so it's
++ * safe to cast one function type to the other
++ */
++typedef void (*efrm_old_work_func_t) (void *p);
++
++#undef INIT_WORK
++#define INIT_WORK(_work, _func) \
++ do { \
++ INIT_LIST_HEAD(&(_work)->entry); \
++ (_work)->pending = 0; \
++ PREPARE_WORK((_work), \
++ (efrm_old_work_func_t) (_func), \
++ (_work)); \
++ } while (0)
++
++#endif
++
++/********************************************************************
++ *
++ * Kfifo API
++ *
++ ********************************************************************/
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
++
++#if !defined(RHEL_RELEASE_CODE) || (RHEL_RELEASE_CODE < 1029)
++typedef unsigned gfp_t;
++#endif
++
++#define HAS_NO_KFIFO
++
++struct kfifo {
++ unsigned char *buffer; /* the buffer holding the data */
++ unsigned int size; /* the size of the allocated buffer */
++ unsigned int in; /* data is added at offset (in % size) */
++ unsigned int out; /* data is extracted from off. (out % size) */
++ spinlock_t *lock; /* protects concurrent modifications */
++};
++
++extern struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
++ gfp_t gfp_mask, spinlock_t *lock);
++extern struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask,
++ spinlock_t *lock);
++extern void kfifo_free(struct kfifo *fifo);
++extern unsigned int __kfifo_put(struct kfifo *fifo,
++ unsigned char *buffer, unsigned int len);
++extern unsigned int __kfifo_get(struct kfifo *fifo,
++ unsigned char *buffer, unsigned int len);
++
++/**
++ * kfifo_put - puts some data into the FIFO
++ * @fifo: the fifo to be used.
++ * @buffer: the data to be added.
++ * @len: the length of the data to be added.
++ *
++ * This function copies at most @len bytes from the @buffer into
++ * the FIFO depending on the free space, and returns the number of
++ * bytes copied.
++ */
++static inline unsigned int
++kfifo_put(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
++{
++ unsigned long flags;
++ unsigned int ret;
++
++ spin_lock_irqsave(fifo->lock, flags);
++
++ ret = __kfifo_put(fifo, buffer, len);
++
++ spin_unlock_irqrestore(fifo->lock, flags);
++
++ return ret;
++}
++
++/**
++ * kfifo_get - gets some data from the FIFO
++ * @fifo: the fifo to be used.
++ * @buffer: where the data must be copied.
++ * @len: the size of the destination buffer.
++ *
++ * This function copies at most @len bytes from the FIFO into the
++ * @buffer and returns the number of copied bytes.
++ */
++static inline unsigned int
++kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
++{
++ unsigned long flags;
++ unsigned int ret;
++
++ spin_lock_irqsave(fifo->lock, flags);
++
++ ret = __kfifo_get(fifo, buffer, len);
++
++ /*
++ * optimization: if the FIFO is empty, set the indices to 0
++ * so we don't wrap the next time
++ */
++ if (fifo->in == fifo->out)
++ fifo->in = fifo->out = 0;
++
++ spin_unlock_irqrestore(fifo->lock, flags);
++
++ return ret;
++}
++
++/**
++ * __kfifo_len - returns the number of bytes available in the FIFO, no locking version
++ * @fifo: the fifo to be used.
++ */
++static inline unsigned int __kfifo_len(struct kfifo *fifo)
++{
++ return fifo->in - fifo->out;
++}
++
++/**
++ * kfifo_len - returns the number of bytes available in the FIFO
++ * @fifo: the fifo to be used.
++ */
++static inline unsigned int kfifo_len(struct kfifo *fifo)
++{
++ unsigned long flags;
++ unsigned int ret;
++
++ spin_lock_irqsave(fifo->lock, flags);
++
++ ret = __kfifo_len(fifo);
++
++ spin_unlock_irqrestore(fifo->lock, flags);
++
++ return ret;
++}
++
++#else
++#include <linux/kfifo.h>
++#endif
++
++static inline void kfifo_vfree(struct kfifo *fifo)
++{
++ vfree(fifo->buffer);
++ kfree(fifo);
++}
++
++#endif /* __CI_EFRM_SYSDEP_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,171 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains public API for VI resource.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_VI_RESOURCE_H__
++#define __CI_EFRM_VI_RESOURCE_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efrm/resource.h>
++#include <ci/efrm/debug.h>
++
++struct vi_resource;
++
++/* Make these inline instead of macros for type checking */
++static inline struct vi_resource *
++efrm_to_vi_resource(struct efrm_resource *rs)
++{
++ EFRM_ASSERT(EFRM_RESOURCE_TYPE(rs->rs_handle) == EFRM_RESOURCE_VI);
++ return (struct vi_resource *) rs;
++}
++static inline struct
++efrm_resource *efrm_from_vi_resource(struct vi_resource *rs)
++{
++ return (struct efrm_resource *)rs;
++}
++
++#define EFAB_VI_RESOURCE_INSTANCE(virs) \
++ EFRM_RESOURCE_INSTANCE(efrm_from_vi_resource(virs)->rs_handle)
++
++#define EFAB_VI_RESOURCE_PRI_ARG(virs) \
++ EFRM_RESOURCE_PRI_ARG(efrm_from_vi_resource(virs)->rs_handle)
++
++extern int
++efrm_vi_resource_alloc(struct vi_resource *evq_virs,
++ uint16_t vi_flags, int32_t evq_capacity,
++ int32_t txq_capacity, int32_t rxq_capacity,
++ uint8_t tx_q_tag, uint8_t rx_q_tag,
++ struct vi_resource **virs_in_out,
++ uint32_t *out_io_mmap_bytes,
++ uint32_t *out_mem_mmap_bytes,
++ uint32_t *out_txq_capacity,
++ uint32_t *out_rxq_capacity);
++
++static inline void efrm_vi_resource_ref(struct vi_resource *virs)
++{
++ atomic_inc(&efrm_from_vi_resource(virs)->rs_ref_count);
++}
++
++/* efrm_vi_resource_free should be called only if
++ * __efrm_resource_ref_count_zero() returned true.
++ * The easiest way is to call efrm_vi_resource_release() */
++extern void efrm_vi_resource_free(struct vi_resource *virs);
++static inline void efrm_vi_resource_release(struct vi_resource *virs)
++{
++ unsigned id;
++ struct efrm_resource *rs = efrm_from_vi_resource(virs);
++
++ id = EFRM_RESOURCE_INSTANCE(rs->rs_handle);
++
++ if (atomic_dec_and_test(&rs->rs_ref_count)) {
++ if (__efrm_resource_ref_count_zero(EFRM_RESOURCE_VI, id)) {
++ EFRM_ASSERT(EFRM_RESOURCE_INSTANCE(rs->rs_handle) ==
++ id);
++ efrm_vi_resource_free(virs);
++ }
++ }
++}
++
++/*--------------------------------------------------------------------
++ *
++ * eventq handling
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Reset an event queue and clear any associated timers */
++extern void efrm_eventq_reset(struct vi_resource *virs, int nic_index);
++
++/*! Register a kernel-level handler for the event queue. This function is
++ * called whenever a timer expires, or whenever the event queue is woken
++ * but no thread is blocked on it.
++ *
++ * This function returns -EBUSY if a callback is already installed.
++ *
++ * \param rs Event-queue resource
++ * \param handler Callback-handler
++ * \param arg Argument to pass to callback-handler
++ * \return Status code
++ */
++extern int
++efrm_eventq_register_callback(struct vi_resource *rs,
++ void (*handler)(void *arg, int is_timeout,
++ struct efhw_nic *nic),
++ void *arg);
++
++/*! Kill the kernel-level callback.
++ *
++ * This function stops the timer from running and unregisters the callback
++ * function. It waits for any running timeout handlers to complete before
++ * returning.
++ *
++ * \param rs Event-queue resource
++ * \return Nothing
++ */
++extern void efrm_eventq_kill_callback(struct vi_resource *rs);
++
++/*! Ask the NIC to generate a wakeup when an event is next delivered. */
++extern void efrm_eventq_request_wakeup(struct vi_resource *rs,
++ unsigned current_ptr,
++ unsigned nic_index);
++
++/*! Register a kernel-level handler for flush completions.
++ * \TODO Currently, it is unsafe to install a callback more than once.
++ *
++ * \param rs VI resource being flushed.
++ * \param handler Callback handler function.
++ * \param arg Argument to be passed to handler.
++ */
++extern void
++efrm_vi_register_flush_callback(struct vi_resource *rs,
++ void (*handler)(void *),
++ void *arg);
++
++int efrm_vi_resource_flush_retry(struct vi_resource *virs);
++
++/*! Comment? */
++extern int efrm_pt_flush(struct vi_resource *);
++
++/*! Comment? */
++extern int efrm_pt_pace(struct vi_resource *, unsigned int val);
++
++uint32_t efrm_vi_rm_txq_bytes(struct vi_resource *virs
++ /*,struct efhw_nic *nic */ );
++uint32_t efrm_vi_rm_rxq_bytes(struct vi_resource *virs
++ /*,struct efhw_nic *nic */ );
++uint32_t efrm_vi_rm_evq_bytes(struct vi_resource *virs
++ /*,struct efhw_nic *nic */ );
++
++#endif /* __CI_EFRM_VI_RESOURCE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,182 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains type definitions for VI resource. These types
++ * may be used outside of the SFC resource driver, but such use is not
++ * recommended.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__
++#define __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__
++
++#include <ci/efhw/common.h>
++#include <ci/efrm/vi_resource.h>
++#include <ci/efrm/nic_set.h>
++
++#define EFRM_VI_RM_DMA_QUEUE_COUNT 2
++#define EFRM_VI_RM_DMA_QUEUE_TX 0
++#define EFRM_VI_RM_DMA_QUEUE_RX 1
++
++/** Numbers of bits which can be set in the evq_state member of
++ * vi_resource_evq_info. */
++enum {
++ /** This bit is set if a wakeup has been requested on the NIC. */
++ VI_RESOURCE_EVQ_STATE_WAKEUP_PENDING,
++ /** This bit is set if the wakeup is valid for the sleeping
++ * process. */
++ VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
++ /** This bit is set if a wakeup or timeout event is currently being
++ * processed. */
++ VI_RESOURCE_EVQ_STATE_BUSY,
++};
++#define VI_RESOURCE_EVQ_STATE(X) \
++ (((int32_t)1) << (VI_RESOURCE_EVQ_STATE_##X))
++
++/** Information about an event queue. */
++struct vi_resource_evq_info {
++ /** Flag bits indicating the state of wakeups. */
++ unsigned long evq_state;
++ /** A pointer to the resource instance for this queue. This member
++ * is only valid if evq_state is non-zero or the resource is known
++ * to have a non-zero reference count. */
++ struct vi_resource *evq_virs;
++};
++
++#ifdef __ci_ul_driver__
++#define EFRM_VI_USE_WORKQUEUE 0
++#else
++#define EFRM_VI_USE_WORKQUEUE 1
++#endif
++
++/*! Global information for the VI resource manager. */
++struct vi_resource_manager {
++ struct efrm_resource_manager rm;
++
++ struct kfifo *instances_with_timer;
++ int with_timer_base;
++ int with_timer_limit;
++ struct kfifo *instances_with_interrupt;
++ int with_interrupt_base;
++ int with_interrupt_limit;
++
++ bool iscsi_dmaq_instance_is_free;
++ struct vi_resource_evq_info *evq_infos;
++
++ /* We keep VI resources which need flushing on these lists. The VI
++ * is put on the outstanding list when the flush request is issued
++ * to the hardware and removed when the flush event arrives. The
++ * hardware can only handle a limited number of RX flush requests at
++ * once, so VIs are placed in the waiting list until the flush can
++ * be issued. Flushes can be requested by the client or internally
++ * by the VI resource manager. In the former case, the reference
++ * count must be non-zero for the duration of the flush and in the
++ * later case, the reference count must be zero. */
++ struct list_head rx_flush_waiting_list;
++ struct list_head rx_flush_outstanding_list;
++ struct list_head tx_flush_outstanding_list;
++ int rx_flush_outstanding_count;
++
++ /* once the flush has happened we push the close into the work queue
++ * so its OK on Windows to free the resources (Bug 3469). Resources
++ * on this list have zero reference count.
++ */
++ struct list_head close_pending;
++ struct work_struct work_item;
++#if EFRM_VI_USE_WORKQUEUE
++ struct workqueue_struct *workqueue;
++#endif
++};
++
++struct vi_resource_nic_info {
++ struct eventq_resource_hardware evq_pages;
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ efhw_iopages_t dmaq_pages[EFRM_VI_RM_DMA_QUEUE_COUNT];
++#endif
++};
++
++struct vi_resource {
++ /* Some macros make the assumption that the struct efrm_resource is
++ * the first member of a struct vi_resource. */
++ struct efrm_resource rs;
++ atomic_t evq_refs; /*!< Number of users of the event queue. */
++
++ efrm_nic_set_t nic_set;
++
++ uint32_t bar_mmap_bytes;
++ uint32_t mem_mmap_bytes;
++
++ int32_t evq_capacity;
++ int32_t dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_COUNT];
++
++ uint8_t dmaq_tag[EFRM_VI_RM_DMA_QUEUE_COUNT];
++ uint16_t flags;
++
++ /* we keep PT endpoints that have been destroyed on a list
++ * until we have seen their TX and RX DMAQs flush complete
++ * (see Bug 1217)
++ */
++ struct list_head rx_flush_link;
++ struct list_head tx_flush_link;
++ efrm_nic_set_t rx_flush_nic_set;
++ efrm_nic_set_t rx_flush_outstanding_nic_set;
++ efrm_nic_set_t tx_flush_nic_set;
++ uint64_t flush_time;
++ int flush_count;
++
++ void (*flush_callback_fn)(void *);
++ void *flush_callback_arg;
++
++ void (*evq_callback_fn) (void *arg, int is_timeout,
++ struct efhw_nic *nic);
++ void *evq_callback_arg;
++
++ struct vi_resource *evq_virs; /*!< EVQ for DMA queues */
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ struct efhw_buffer_table_allocation
++ dmaq_buf_tbl_alloc[EFRM_VI_RM_DMA_QUEUE_COUNT];
++#endif
++
++ struct vi_resource_nic_info nic_info[EFHW_MAX_NR_DEVS];
++};
++
++#undef vi_resource
++#define vi_resource(rs1) container_of((rs1), struct vi_resource, rs)
++
++static inline dma_addr_t
++efrm_eventq_dma_addr(struct vi_resource *virs, uint32_t nic_index)
++{
++ struct eventq_resource_hardware *hw;
++ EFRM_ASSERT(efrm_nic_set_read(&virs->nic_set, nic_index));
++
++ hw = &(virs->nic_info[nic_index].evq_pages);
++
++ return efhw_iopages_dma_addr(&(hw->iobuff)) + hw->iobuff_off;
++}
++
++#endif /* __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,83 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains private API for VI resource. The API is not designed
++ * to be used outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_VI_RESOURCE_PRIVATE_H__
++#define __CI_EFRM_VI_RESOURCE_PRIVATE_H__
++
++#include <ci/efhw/common.h>
++#include <ci/efrm/vi_resource_manager.h>
++
++extern struct vi_resource_manager *efrm_vi_manager;
++
++/*************************************************************************/
++
++extern void efrm_vi_rm_delayed_free(struct work_struct *data);
++
++extern void efrm_vi_rm_salvage_flushed_vis(void);
++
++void efrm_vi_rm_free_flushed_resource(struct vi_resource *virs);
++
++void efrm_vi_rm_init_dmaq(struct vi_resource *virs, int queue_index,
++ struct efhw_nic *nic);
++
++static inline int
++efrm_eventq_bytes(struct vi_resource *virs, uint32_t nic_index)
++{
++ EFRM_ASSERT(efrm_nic_set_read(&virs->nic_set, nic_index));
++
++ return efrm_vi_rm_evq_bytes(virs);
++}
++
++static inline efhw_event_t *
++efrm_eventq_base(struct vi_resource *virs, uint32_t nic_index)
++{
++ struct eventq_resource_hardware *hw;
++
++ EFRM_ASSERT(efrm_nic_set_read(&virs->nic_set, nic_index));
++
++ hw = &(virs->nic_info[nic_index].evq_pages);
++
++ return (efhw_event_t *) (efhw_iopages_ptr(&(hw->iobuff)) +
++ hw->iobuff_off);
++}
++
++/*! Wakeup handler, see efhw_ev_handler_t for prototype */
++extern void efrm_handle_wakeup_event(struct efhw_nic *nic, efhw_event_t *ev);
++
++/*! Timeout handler, see efhw_ev_handler_t for prototype */
++extern void efrm_handle_timeout_event(struct efhw_nic *nic, efhw_event_t *ev);
++
++/*! DMA flush handler, see efhw_ev_handler_t for prototype */
++extern void efrm_handle_dmaq_flushed(struct efhw_nic *nic, int instance,
++ int rx_flush);
++
++#endif /* __CI_EFRM_VI_RESOURCE_PRIVATE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/driverlink_new.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/driverlink_new.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/driverlink_new.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/driverlink_new.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,290 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains driverlink code which interacts with the sfc network
++ * driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "linux_resource_internal.h"
++#include "driverlink_api.h"
++#include "kernel_compat.h"
++#include <ci/efhw/falcon.h>
++
++#include <linux/rtnetlink.h>
++#include <linux/netdevice.h>
++
++/* The DL driver and associated calls */
++static int efrm_dl_probe(struct efx_dl_device *efrm_dev,
++ const struct net_device *net_dev,
++ const struct efx_dl_device_info *dev_info,
++ const char *silicon_rev);
++
++static void efrm_dl_remove(struct efx_dl_device *efrm_dev);
++
++static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev);
++
++static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok);
++
++static void efrm_dl_mtu_changed(struct efx_dl_device *, int);
++static void efrm_dl_event_falcon(struct efx_dl_device *efx_dev, void *p_event);
++
++static struct efx_dl_driver efrm_dl_driver = {
++ .name = "resource",
++ .probe = efrm_dl_probe,
++ .remove = efrm_dl_remove,
++ .reset_suspend = efrm_dl_reset_suspend,
++ .reset_resume = efrm_dl_reset_resume
++};
++
++static void
++init_vi_resource_dimensions(struct vi_resource_dimensions *rd,
++ const struct efx_dl_falcon_resources *res)
++{
++ rd->evq_timer_min = res->evq_timer_min;
++ rd->evq_timer_max = res->evq_timer_max;
++ rd->evq_int_min = res->evq_int_min;
++ rd->evq_int_max = res->evq_int_max;
++ rd->rxq_min = res->rxq_min;
++ rd->rxq_max = res->rxq_max;
++ rd->txq_min = res->txq_min;
++ rd->txq_max = res->txq_max;
++ EFRM_TRACE
++ ("Using evq_int(%d-%d) evq_timer(%d-%d) RXQ(%d-%d) TXQ(%d-%d)",
++ res->evq_int_min, res->evq_int_max, res->evq_timer_min,
++ res->evq_timer_max, res->rxq_min, res->rxq_max, res->txq_min,
++ res->txq_max);
++}
++
++#if defined(EFX_NOT_UPSTREAM)
++/* We have a module parameter that can tell us to only load the char driver
++ * for 1 NIC (if there are multiple NICs in the system), and if so which one.
++ * This tells us the PCI bus and slot of the NIC to load for, or -1 to just
++ * load on all NICs (the default).
++ * Value is a hex number in the format
++ * bbbbss
++ * where:
++ * bbbb - PCI bus number
++ * ss - PCI slot number
++ */
++unsigned int only_NIC = -1;
++
++/** @ingroup module_params */
++module_param(only_NIC, uint, 0444);
++MODULE_PARM_DESC(only_NIC,
++ "Initialise sfc_resource driver for one NIC only, "
++ "with specified PCI bus and slot");
++#endif
++
++static int
++efrm_dl_probe(struct efx_dl_device *efrm_dev,
++ const struct net_device *net_dev,
++ const struct efx_dl_device_info *dev_info,
++ const char *silicon_rev)
++{
++ struct vi_resource_dimensions res_dim;
++ struct efx_dl_falcon_resources *res;
++ struct linux_efhw_nic *lnic;
++ struct pci_dev *dev;
++ struct efhw_nic *nic;
++ unsigned probe_flags = 0;
++ int rc;
++
++ efrm_dev->priv = NULL;
++
++ efx_dl_for_each_device_info_matching(dev_info, EFX_DL_FALCON_RESOURCES,
++ struct efx_dl_falcon_resources,
++ hdr, res) {
++ /* break out, leaving res pointing at the falcon resources */
++ break;
++ }
++
++ if (res == NULL) {
++ EFRM_ERR("%s: Unable to find falcon driverlink resources",
++ __FUNCTION__);
++ return -EINVAL;
++ }
++
++ if (res->flags & EFX_DL_FALCON_USE_MSI)
++ probe_flags |= NIC_FLAG_TRY_MSI;
++
++ dev = efrm_dev->pci_dev;
++ if (res->flags & EFX_DL_FALCON_DUAL_FUNC) {
++ unsigned vendor = dev->vendor;
++ EFRM_ASSERT(dev->bus != NULL);
++ dev = NULL;
++
++#if defined(EFX_NOT_UPSTREAM)
++ if (only_NIC != -1 &&
++ (efrm_dev->pci_dev->bus->number !=
++ ((only_NIC >> 8) & 0xFFFF)
++ || PCI_SLOT(efrm_dev->pci_dev->devfn) !=
++ (only_NIC & 0xFF))) {
++ EFRM_NOTICE("Hiding char device %x:%x",
++ efrm_dev->pci_dev->bus->number,
++ PCI_SLOT(efrm_dev->pci_dev->devfn));
++ return -ENODEV;
++ }
++#endif
++
++ while ((dev = pci_get_device(vendor, FALCON_S_DEVID, dev))
++ != NULL) {
++ EFRM_ASSERT(dev->bus != NULL);
++ /* With PCIe (since it's point to point)
++ * the slot ID is usually 0 and
++ * the bus ID changes NIC to NIC, so we really
++ * need to check both. */
++ if (PCI_SLOT(dev->devfn) ==
++ PCI_SLOT(efrm_dev->pci_dev->devfn)
++ && dev->bus->number ==
++ efrm_dev->pci_dev->bus->number)
++ break;
++ }
++ if (dev == NULL) {
++ EFRM_ERR("%s: Unable to find falcon secondary "
++ "PCI device.", __FUNCTION__);
++ return -ENODEV;
++ }
++ pci_dev_put(dev);
++ }
++
++ init_vi_resource_dimensions(&res_dim, res);
++
++ rc = efrm_nic_add(dev, probe_flags, net_dev->dev_addr, &lnic,
++ res->biu_lock,
++ res->buffer_table_min, res->buffer_table_max,
++ &res_dim);
++ if (rc != 0)
++ return rc;
++
++ nic = &lnic->nic;
++ nic->mtu = net_dev->mtu + ETH_HLEN;
++ nic->net_driver_dev = efrm_dev;
++ nic->ifindex = net_dev->ifindex;
++#ifdef HAS_NET_NAMESPACE
++ nic->nd_net = net_dev->nd_net;
++#endif
++ efrm_dev->priv = nic;
++
++ /* Register a callback so we're told when MTU changes.
++ * We dynamically allocate efx_dl_callbacks, because
++ * the callbacks that we want depends on the NIC type.
++ */
++ lnic->dl_callbacks =
++ kmalloc(sizeof(struct efx_dl_callbacks), GFP_KERNEL);
++ if (!lnic->dl_callbacks) {
++ EFRM_ERR("Out of memory (%s)", __FUNCTION__);
++ efrm_nic_del(lnic);
++ return -ENOMEM;
++ }
++ memset(lnic->dl_callbacks, 0, sizeof(*lnic->dl_callbacks));
++ lnic->dl_callbacks->mtu_changed = efrm_dl_mtu_changed;
++
++ if ((res->flags & EFX_DL_FALCON_DUAL_FUNC) == 0) {
++ /* Net driver receives all management events.
++ * Register a callback to receive the ones
++ * we're interested in. */
++ lnic->dl_callbacks->event = efrm_dl_event_falcon;
++ }
++
++ rc = efx_dl_register_callbacks(efrm_dev, lnic->dl_callbacks);
++ if (rc < 0) {
++ EFRM_ERR("%s: efx_dl_register_callbacks failed (%d)",
++ __FUNCTION__, rc);
++ kfree(lnic->dl_callbacks);
++ efrm_nic_del(lnic);
++ return rc;
++ }
++
++ return 0;
++}
++
++/* When we unregister ourselves on module removal, this function will be
++ * called for all the devices we claimed */
++static void efrm_dl_remove(struct efx_dl_device *efrm_dev)
++{
++ struct efhw_nic *nic = efrm_dev->priv;
++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
++ EFRM_TRACE("%s called", __FUNCTION__);
++ if (lnic->dl_callbacks) {
++ efx_dl_unregister_callbacks(efrm_dev, lnic->dl_callbacks);
++ kfree(lnic->dl_callbacks);
++ }
++ if (efrm_dev->priv)
++ efrm_nic_del(lnic);
++ EFRM_TRACE("%s OK", __FUNCTION__);
++}
++
++static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev)
++{
++ EFRM_NOTICE("%s:", __FUNCTION__);
++}
++
++static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok)
++{
++ EFRM_NOTICE("%s: ok=%d", __FUNCTION__, ok);
++}
++
++int efrm_driverlink_register(void)
++{
++ EFRM_TRACE("%s:", __FUNCTION__);
++ return efx_dl_register_driver(&efrm_dl_driver);
++}
++
++void efrm_driverlink_unregister(void)
++{
++ EFRM_TRACE("%s:", __FUNCTION__);
++ efx_dl_unregister_driver(&efrm_dl_driver);
++}
++
++static void efrm_dl_mtu_changed(struct efx_dl_device *efx_dev, int mtu)
++{
++ struct efhw_nic *nic = efx_dev->priv;
++
++ ASSERT_RTNL(); /* Since we're looking at efx_dl_device::port_net_dev */
++
++ EFRM_TRACE("%s: old=%d new=%d", __FUNCTION__, nic->mtu, mtu + ETH_HLEN);
++ /* If this happened we must have agreed to it above */
++ nic->mtu = mtu + ETH_HLEN;
++}
++
++static void efrm_dl_event_falcon(struct efx_dl_device *efx_dev, void *p_event)
++{
++ struct efhw_nic *nic = efx_dev->priv;
++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
++ efhw_event_t *ev = p_event;
++
++ switch (FALCON_EVENT_CODE(ev)) {
++ case FALCON_EVENT_CODE_CHAR:
++ falcon_handle_char_event(nic, lnic->ev_handlers, ev);
++ break;
++ default:
++ EFRM_WARN("%s: unknown event type=%x", __FUNCTION__,
++ (unsigned)FALCON_EVENT_CODE(ev));
++ break;
++ }
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/driver_object.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/driver_object.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/driver_object.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/driver_object.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,174 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains support for the global driver variables.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/nic_table.h>
++#include <ci/efrm/resource.h>
++#include <ci/efrm/debug.h>
++
++/* We use #define rather than static inline here so that the Windows
++ * "prefast" compiler can see its own locking primitive when these
++ * two function are used (and then perform extra checking where they
++ * are used)
++ *
++ * Both macros operate on an irq_flags_t
++*/
++
++#define efrm_driver_lock(irqlock_state) \
++ spin_lock_irqsave(&efrm_nic_table.lock, irqlock_state)
++
++#define efrm_driver_unlock(irqlock_state) \
++ spin_unlock_irqrestore(&efrm_nic_table.lock, \
++ irqlock_state);
++
++/* These routines are all methods on the architecturally singleton
++ global variables: efrm_nic_table, efrm_rm_table.
++
++ I hope we never find a driver model that does not allow global
++ structure variables :) (but that would break almost every driver I've
++ ever seen).
++*/
++
++/*! Exported driver state */
++struct efrm_nic_table efrm_nic_table;
++EXPORT_SYMBOL(efrm_nic_table);
++
++/* Internal table with resource managers.
++ * We'd like to not export it, but we are still using efrm_rm_table
++ * in the char driver. So, it is declared in the private header with
++ * a purpose. */
++struct efrm_resource_manager *efrm_rm_table[EFRM_RESOURCE_NUM];
++EXPORT_SYMBOL(efrm_rm_table);
++
++int efrm_driver_ctor(void)
++{
++ memset(&efrm_nic_table, 0, sizeof(efrm_nic_table));
++ memset(&efrm_rm_table, 0, sizeof(efrm_rm_table));
++
++ spin_lock_init(&efrm_nic_table.lock);
++
++ EFRM_TRACE("%s: driver created", __FUNCTION__);
++ return 0;
++}
++
++int efrm_driver_dtor(void)
++{
++ EFRM_ASSERT(!efrm_nic_table_held());
++
++ spin_lock_destroy(&efrm_nic_table.lock);
++ EFRM_TRACE("%s: driver deleted", __FUNCTION__);
++ return 0;
++}
++
++int efrm_driver_register_nic(struct efhw_nic *nic, int nic_index)
++{
++ int rc = 0;
++ irq_flags_t lock_flags;
++
++ EFRM_ASSERT(nic_index >= 0);
++
++ efrm_driver_lock(lock_flags);
++
++ if (efrm_nic_table_held()) {
++ EFRM_WARN("%s: driver object is in use", __FUNCTION__);
++ rc = -EBUSY;
++ goto done;
++ }
++
++ if (efrm_nic_table.nic_count == EFHW_MAX_NR_DEVS) {
++ EFRM_WARN("%s: filled up NIC table size %d", __FUNCTION__,
++ EFHW_MAX_NR_DEVS);
++ rc = -E2BIG;
++ goto done;
++ }
++
++ EFRM_ASSERT(efrm_nic_table.nic[nic_index] == NULL);
++ efrm_nic_table.nic[nic_index] = nic;
++ nic->index = nic_index;
++
++ if (efrm_nic_table.a_nic == NULL)
++ efrm_nic_table.a_nic = nic;
++
++ efrm_nic_table.nic_count++;
++ efrm_driver_unlock(lock_flags);
++ return rc;
++
++done:
++ efrm_driver_unlock(lock_flags);
++ return rc;
++}
++
++int efrm_driver_unregister_nic(struct efhw_nic *nic)
++{
++ int rc = 0;
++ int nic_index = nic->index;
++ irq_flags_t lock_flags;
++
++ EFRM_ASSERT(nic_index >= 0);
++
++ efrm_driver_lock(lock_flags);
++
++ if (efrm_nic_table_held()) {
++ EFRM_WARN("%s: driver object is in use", __FUNCTION__);
++ rc = -EBUSY;
++ goto done;
++ }
++
++ EFRM_ASSERT(efrm_nic_table.nic[nic_index] == nic);
++
++ nic->index = -1;
++ efrm_nic_table.nic[nic_index] = NULL;
++
++ --efrm_nic_table.nic_count;
++
++ if (efrm_nic_table.a_nic == nic) {
++ if (efrm_nic_table.nic_count == 0) {
++ efrm_nic_table.a_nic = NULL;
++ } else {
++ for (nic_index = 0; nic_index < EFHW_MAX_NR_DEVS;
++ nic_index++) {
++ if (efrm_nic_table.nic[nic_index] != NULL)
++ efrm_nic_table.a_nic =
++ efrm_nic_table.nic[nic_index];
++ }
++ EFRM_ASSERT(efrm_nic_table.a_nic);
++ }
++ }
++
++done:
++ efrm_driver_unlock(lock_flags);
++ return rc;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/efx_vi_shm.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/efx_vi_shm.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/efx_vi_shm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/efx_vi_shm.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,701 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides implementation of EFX VI API, used from Xen
++ * acceleration driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "linux_resource_internal.h"
++#include <ci/efrm/nic_table.h>
++#include <ci/efrm/vi_resource_manager.h>
++#include <ci/driver/resource/efx_vi.h>
++#include <ci/efrm/filter.h>
++#include <ci/efrm/buffer_table.h>
++#include <linux/pci.h>
++#include "kernel_compat.h"
++
++#if EFX_VI_STATIC_FILTERS
++struct filter_list_t {
++ struct filter_list_t *next;
++ struct filter_resource *fres;
++};
++#endif
++
++struct efx_vi_state {
++ struct vi_resource *vi_res;
++
++ int nic_index;
++
++ void (*callback_fn)(void *arg, int is_timeout);
++ void *callback_arg;
++
++ struct completion flush_completion;
++
++#if EFX_VI_STATIC_FILTERS
++ struct filter_list_t fres[EFX_VI_STATIC_FILTERS];
++ struct filter_list_t *free_fres;
++ struct filter_list_t *used_fres;
++#endif
++};
++
++static void efx_vi_flush_complete(void *state_void)
++{
++ struct efx_vi_state *state = (struct efx_vi_state *)state_void;
++
++ complete(&state->flush_completion);
++}
++
++static inline int alloc_ep(struct efx_vi_state *state)
++{
++ int rc;
++
++ rc = efrm_vi_resource_alloc(NULL, EFHW_VI_JUMBO_EN,
++ efx_vi_eventq_size,
++ FALCON_DMA_Q_DEFAULT_TX_SIZE,
++ FALCON_DMA_Q_DEFAULT_RX_SIZE,
++ 0, 0, &state->vi_res, NULL, NULL, NULL,
++ NULL);
++ if (rc < 0) {
++ EFRM_ERR("%s: ERROR efrm_vi_resource_alloc error %d",
++ __FUNCTION__, rc);
++ return rc;
++ }
++
++ efrm_vi_register_flush_callback(state->vi_res, &efx_vi_flush_complete,
++ (void *)state);
++
++ return 0;
++}
++
++static int free_ep(struct efx_vi_state *efx_state)
++{
++ efrm_vi_resource_release(efx_state->vi_res);
++
++ return 0;
++}
++
++#if EFX_VI_STATIC_FILTERS
++static int efx_vi_alloc_static_filters(struct efx_vi_state *efx_state)
++{
++ int i;
++ int rc;
++
++ efx_state->free_fres = efx_state->used_fres = NULL;
++
++ for (i = 0; i < EFX_VI_STATIC_FILTERS; i++) {
++ rc = efrm_filter_resource_alloc(efx_state->vi_res,
++ &efx_state->fres[i].fres);
++ if (rc < 0) {
++ EFRM_ERR("%s: efrm_filter_resource_alloc failed: %d",
++ __FUNCTION__, rc);
++ while (i > 0) {
++ i--;
++ efrm_filter_resource_release(efx_state->
++ fres[i].fres);
++ }
++ efx_state->free_fres = NULL;
++ return rc;
++ }
++ efx_state->fres[i].next = efx_state->free_fres;
++ efx_state->free_fres = &efx_state->fres[i];
++ }
++
++ return 0;
++}
++#endif
++
++int efx_vi_alloc(struct efx_vi_state **vih_out, int nic_index)
++{
++ struct efx_vi_state *efx_state;
++ int rc;
++
++ BUG_ON(nic_index < 0 || nic_index >= EFHW_MAX_NR_DEVS);
++
++ efx_state = kmalloc(sizeof(struct efx_vi_state), GFP_KERNEL);
++
++ if (!efx_state) {
++ EFRM_ERR("%s: failed to allocate memory for efx_vi_state",
++ __FUNCTION__);
++ rc = -ENOMEM;
++ goto fail;
++ }
++
++ efx_state->nic_index = nic_index;
++ init_completion(&efx_state->flush_completion);
++
++ /* basically allocate_pt_endpoint() */
++ rc = alloc_ep(efx_state);
++ if (rc) {
++ EFRM_ERR("%s: alloc_ep failed: %d", __FUNCTION__, rc);
++ goto fail_no_pt;
++ }
++#if EFX_VI_STATIC_FILTERS
++ /* Statically allocate a set of filter resources - removes the
++ restriction on not being able to use efx_vi_filter() from
++ in_atomic() */
++ rc = efx_vi_alloc_static_filters(efx_state);
++ if (rc)
++ goto fail_no_filters;
++#endif
++
++ *vih_out = efx_state;
++
++ return 0;
++#if EFX_VI_STATIC_FILTERS
++fail_no_filters:
++ free_ep(efx_state);
++#endif
++fail_no_pt:
++ kfree(efx_state);
++fail:
++ return rc;
++}
++EXPORT_SYMBOL(efx_vi_alloc);
++
++void efx_vi_free(struct efx_vi_state *vih)
++{
++ struct efx_vi_state *efx_state = vih;
++
++ /* TODO flush dma channels, init dma queues?. See ef_free_vnic() */
++#if EFX_VI_STATIC_FILTERS
++ int i;
++
++ for (i = 0; i < EFX_VI_STATIC_FILTERS; i++)
++ efrm_filter_resource_release(efx_state->fres[i].fres);
++#endif
++
++ if (efx_state->vi_res)
++ free_ep(efx_state);
++
++ kfree(efx_state);
++}
++EXPORT_SYMBOL(efx_vi_free);
++
++void efx_vi_reset(struct efx_vi_state *vih)
++{
++ struct efx_vi_state *efx_state = vih;
++
++ efrm_pt_flush(efx_state->vi_res);
++
++ while (wait_for_completion_timeout(&efx_state->flush_completion, HZ)
++ == 0)
++ efrm_vi_resource_flush_retry(efx_state->vi_res);
++
++ /* Bosch the eventq */
++ efrm_eventq_reset(efx_state->vi_res, 0);
++ return;
++}
++EXPORT_SYMBOL(efx_vi_reset);
++
++static void
++efx_vi_eventq_callback(void *context, int is_timeout, struct efhw_nic *nic)
++{
++ struct efx_vi_state *efx_state = (struct efx_vi_state *)context;
++
++ EFRM_ASSERT(efx_state->callback_fn);
++
++ return efx_state->callback_fn(efx_state->callback_arg, is_timeout);
++}
++
++int
++efx_vi_eventq_register_callback(struct efx_vi_state *vih,
++ void (*callback)(void *context, int is_timeout),
++ void *context)
++{
++ struct efx_vi_state *efx_state = vih;
++
++ efx_state->callback_fn = callback;
++ efx_state->callback_arg = context;
++
++ /* Register the eventq timeout event callback */
++ efrm_eventq_register_callback(efx_state->vi_res,
++ efx_vi_eventq_callback, efx_state);
++
++ return 0;
++}
++EXPORT_SYMBOL(efx_vi_eventq_register_callback);
++
++int efx_vi_eventq_kill_callback(struct efx_vi_state *vih)
++{
++ struct efx_vi_state *efx_state = vih;
++
++ if (efx_state->vi_res->evq_callback_fn)
++ efrm_eventq_kill_callback(efx_state->vi_res);
++
++ efx_state->callback_fn = NULL;
++ efx_state->callback_arg = NULL;
++
++ return 0;
++}
++EXPORT_SYMBOL(efx_vi_eventq_kill_callback);
++
++struct efx_vi_dma_map_state {
++ struct efhw_buffer_table_allocation bt_handle;
++ int n_pages;
++ dma_addr_t *dma_addrs;
++};
++
++int
++efx_vi_dma_map_pages(struct efx_vi_state *vih, struct page **pages,
++ int n_pages, struct efx_vi_dma_map_state **dmh_out)
++{
++ struct efx_vi_state *efx_state = vih;
++ int order = fls(n_pages - 1), rc, i, evq_id;
++ dma_addr_t dma_addr;
++ struct efx_vi_dma_map_state *dm_state;
++
++ if (n_pages != (1 << order)) {
++ EFRM_WARN("%s: Can only allocate buffers in power of 2 "
++ "sizes (not %d)", __FUNCTION__, n_pages);
++ return -EINVAL;
++ }
++
++ dm_state = kmalloc(sizeof(struct efx_vi_dma_map_state), GFP_KERNEL);
++ if (!dm_state)
++ return -ENOMEM;
++
++ dm_state->dma_addrs = kmalloc(sizeof(dma_addr_t) * n_pages,
++ GFP_KERNEL);
++ if (!dm_state->dma_addrs) {
++ kfree(dm_state);
++ return -ENOMEM;
++ }
++
++ rc = efrm_buffer_table_alloc(order, &dm_state->bt_handle);
++ if (rc < 0) {
++ kfree(dm_state->dma_addrs);
++ kfree(dm_state);
++ return rc;
++ }
++
++ evq_id = EFRM_RESOURCE_INSTANCE(efx_state->vi_res->rs.rs_handle);
++ for (i = 0; i < n_pages; i++) {
++ /* TODO do we need to get_page() here ? */
++
++ dma_addr = pci_map_page
++ (linux_efhw_nic(efrm_nic_table.nic[efx_state->nic_index])->
++ pci_dev, pages[i], 0, PAGE_SIZE, PCI_DMA_TODEVICE);
++
++ efrm_buffer_table_set(&dm_state->bt_handle, i, dma_addr,
++ evq_id);
++
++ dm_state->dma_addrs[i] = dma_addr;
++
++ /* Would be nice to not have to call commit each time, but
++ * comment says there are hardware restrictions on how often
++ * you can go without it, so do this to be safe */
++ efrm_buffer_table_commit();
++ }
++
++ dm_state->n_pages = n_pages;
++
++ *dmh_out = dm_state;
++
++ return 0;
++}
++EXPORT_SYMBOL(efx_vi_dma_map_pages);
++
++/* Function needed as Xen can't get pages for grants in dom0, but can
++ get dma address */
++int
++efx_vi_dma_map_addrs(struct efx_vi_state *vih,
++ unsigned long long *bus_dev_addrs,
++ int n_pages, struct efx_vi_dma_map_state **dmh_out)
++{
++ struct efx_vi_state *efx_state = vih;
++ int order = fls(n_pages - 1), rc, i, evq_id;
++ dma_addr_t dma_addr;
++ struct efx_vi_dma_map_state *dm_state;
++
++ if (n_pages != (1 << order)) {
++ EFRM_WARN("%s: Can only allocate buffers in power of 2 "
++ "sizes (not %d)", __FUNCTION__, n_pages);
++ return -EINVAL;
++ }
++
++ dm_state = kmalloc(sizeof(struct efx_vi_dma_map_state), GFP_KERNEL);
++ if (!dm_state)
++ return -ENOMEM;
++
++ dm_state->dma_addrs = kmalloc(sizeof(dma_addr_t) * n_pages,
++ GFP_KERNEL);
++ if (!dm_state->dma_addrs) {
++ kfree(dm_state);
++ return -ENOMEM;
++ }
++
++ rc = efrm_buffer_table_alloc(order, &dm_state->bt_handle);
++ if (rc < 0) {
++ kfree(dm_state->dma_addrs);
++ kfree(dm_state);
++ return rc;
++ }
++
++ evq_id = EFRM_RESOURCE_INSTANCE(efx_state->vi_res->rs.rs_handle);
++#if 0
++ EFRM_WARN("%s: mapping %d pages to evq %d, bt_ids %d-%d\n",
++ __FUNCTION__, n_pages, evq_id,
++ dm_state->bt_handle.base,
++ dm_state->bt_handle.base + n_pages);
++#endif
++ for (i = 0; i < n_pages; i++) {
++
++ dma_addr = (dma_addr_t)bus_dev_addrs[i];
++
++ efrm_buffer_table_set(&dm_state->bt_handle, i, dma_addr,
++ evq_id);
++
++ dm_state->dma_addrs[i] = dma_addr;
++
++ /* Would be nice to not have to call commit each time, but
++ * comment says there are hardware restrictions on how often
++ * you can go without it, so do this to be safe */
++ efrm_buffer_table_commit();
++ }
++
++ dm_state->n_pages = n_pages;
++
++ *dmh_out = dm_state;
++
++ return 0;
++}
++EXPORT_SYMBOL(efx_vi_dma_map_addrs);
++
++void
++efx_vi_dma_unmap_pages(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh)
++{
++ struct efx_vi_state *efx_state = vih;
++ struct efx_vi_dma_map_state *dm_state =
++ (struct efx_vi_dma_map_state *)dmh;
++ int i;
++
++ efrm_buffer_table_free(&dm_state->bt_handle);
++
++ for (i = 0; i < dm_state->n_pages; ++i)
++ pci_unmap_page(linux_efhw_nic
++ (efrm_nic_table.nic[efx_state->nic_index])->pci_dev,
++ dm_state->dma_addrs[i], PAGE_SIZE, PCI_DMA_TODEVICE);
++
++ kfree(dm_state->dma_addrs);
++ kfree(dm_state);
++
++ return;
++}
++EXPORT_SYMBOL(efx_vi_dma_unmap_pages);
++
++void
++efx_vi_dma_unmap_addrs(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh)
++{
++ struct efx_vi_dma_map_state *dm_state =
++ (struct efx_vi_dma_map_state *)dmh;
++
++ efrm_buffer_table_free(&dm_state->bt_handle);
++
++ kfree(dm_state->dma_addrs);
++ kfree(dm_state);
++
++ return;
++}
++EXPORT_SYMBOL(efx_vi_dma_unmap_addrs);
++
++unsigned
++efx_vi_dma_get_map_addr(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh)
++{
++ struct efx_vi_dma_map_state *dm_state =
++ (struct efx_vi_dma_map_state *)dmh;
++
++ return EFHW_BUFFER_ADDR(dm_state->bt_handle.base, 0);
++}
++EXPORT_SYMBOL(efx_vi_dma_get_map_addr);
++
++#if EFX_VI_STATIC_FILTERS
++static int
++get_filter(struct efx_vi_state *efx_state,
++ efrm_resource_handle_t pthandle, struct filter_resource **fres_out)
++{
++ struct filter_list_t *flist;
++ if (efx_state->free_fres == NULL)
++ return -ENOMEM;
++ else {
++ flist = efx_state->free_fres;
++ efx_state->free_fres = flist->next;
++ flist->next = efx_state->used_fres;
++ efx_state->used_fres = flist;
++ *fres_out = flist->fres;
++ return 0;
++ }
++}
++#endif
++
++static void
++release_filter(struct efx_vi_state *efx_state, struct filter_resource *fres)
++{
++#if EFX_VI_STATIC_FILTERS
++ struct filter_list_t *flist = efx_state->used_fres, *prev = NULL;
++ while (flist) {
++ if (flist->fres == fres) {
++ if (prev)
++ prev->next = flist->next;
++ else
++ efx_state->used_fres = flist->next;
++ flist->next = efx_state->free_fres;
++ efx_state->free_fres = flist;
++ return;
++ }
++ prev = flist;
++ flist = flist->next;
++ }
++ EFRM_ERR("%s: couldn't find filter", __FUNCTION__);
++#else
++ return efrm_filter_resource_release(fres);
++#endif
++}
++
++int
++efx_vi_filter(struct efx_vi_state *vih, int protocol,
++ unsigned ip_addr_be32, int port_le16,
++ struct filter_resource_t **fh_out)
++{
++ struct efx_vi_state *efx_state = vih;
++ struct filter_resource *frs;
++ int rc;
++
++#if EFX_VI_STATIC_FILTERS
++ rc = get_filter(efx_state, efx_state->vi_res->rs.rs_handle, &frs);
++#else
++ rc = efrm_filter_resource_alloc(efx_state->vi_res, &frs);
++#endif
++ if (rc < 0)
++ return rc;
++
++ /* Add the hardware filter. We pass in the source port and address
++ * as 0 (wildcard) to minimise the number of filters needed. */
++ if (protocol == IPPROTO_TCP) {
++ rc = efrm_filter_resource_tcp_set(frs, 0, 0, ip_addr_be32,
++ port_le16);
++ } else {
++ rc = efrm_filter_resource_udp_set(frs, 0, 0, ip_addr_be32,
++ port_le16);
++ }
++
++ *fh_out = (struct filter_resource_t *)frs;
++
++ return rc;
++}
++EXPORT_SYMBOL(efx_vi_filter);
++
++int
++efx_vi_filter_stop(struct efx_vi_state *vih, struct filter_resource_t *fh)
++{
++ struct efx_vi_state *efx_state = vih;
++ struct filter_resource *frs = (struct filter_resource *)fh;
++ int rc;
++
++ rc = efrm_filter_resource_clear(frs);
++ release_filter(efx_state, frs);
++
++ return rc;
++}
++EXPORT_SYMBOL(efx_vi_filter_stop);
++
++int
++efx_vi_hw_resource_get_virt(struct efx_vi_state *vih,
++ struct efx_vi_hw_resource_metadata *mdata,
++ struct efx_vi_hw_resource *hw_res_array,
++ int *length)
++{
++ EFRM_NOTICE("%s: TODO!", __FUNCTION__);
++
++ return 0;
++}
++EXPORT_SYMBOL(efx_vi_hw_resource_get_virt);
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++int
++efx_vi_hw_resource_get_phys(struct efx_vi_state *vih,
++ struct efx_vi_hw_resource_metadata *mdata,
++ struct efx_vi_hw_resource *hw_res_array,
++ int *length)
++{
++ struct efx_vi_state *efx_state = vih;
++ int i, ni = efx_state->nic_index;
++ struct linux_efhw_nic *lnic = linux_efhw_nic(efrm_nic_table.nic[ni]);
++ unsigned long phys = lnic->ctr_ap_pci_addr;
++ struct efrm_resource *ep_res = &efx_state->vi_res->rs;
++ unsigned ep_mmap_bytes;
++
++ if (*length < EFX_VI_HW_RESOURCE_MAXSIZE)
++ return -EINVAL;
++
++ mdata->version = 0;
++
++ mdata->nic_arch = efrm_nic_table.nic[ni]->devtype.arch;
++ mdata->nic_variant = efrm_nic_table.nic[ni]->devtype.variant;
++ mdata->nic_revision = efrm_nic_table.nic[ni]->devtype.revision;
++
++ mdata->evq_order =
++ efx_state->vi_res->nic_info[ni].evq_pages.iobuff.order;
++ mdata->evq_offs = efx_state->vi_res->nic_info[ni].evq_pages.iobuff_off;
++ mdata->evq_capacity = efx_vi_eventq_size;
++ mdata->instance = EFRM_RESOURCE_INSTANCE(ep_res->rs_handle);
++ mdata->rx_capacity = FALCON_DMA_Q_DEFAULT_RX_SIZE;
++ mdata->tx_capacity = FALCON_DMA_Q_DEFAULT_TX_SIZE;
++
++ ep_mmap_bytes = FALCON_DMA_Q_DEFAULT_MMAP;
++ EFRM_ASSERT(ep_mmap_bytes == PAGE_SIZE * 2);
++
++#ifndef NDEBUG
++ {
++ /* Sanity about doorbells */
++ unsigned long tx_dma_page_addr, rx_dma_page_addr;
++
++ /* get rx doorbell address */
++ rx_dma_page_addr =
++ phys + falcon_rx_dma_page_addr(mdata->instance);
++ /* get tx doorbell address */
++ tx_dma_page_addr =
++ phys + falcon_tx_dma_page_addr(mdata->instance);
++
++ /* Check the lower bits of the TX doorbell will be
++ * consistent. */
++ EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST &
++ FALCON_DMA_PAGE_MASK) ==
++ (TX_DESC_UPD_REG_PAGE123K_OFST &
++ FALCON_DMA_PAGE_MASK));
++
++ /* Check the lower bits of the RX doorbell will be
++ * consistent. */
++ EFRM_ASSERT((RX_DESC_UPD_REG_PAGE4_OFST &
++ FALCON_DMA_PAGE_MASK) ==
++ (RX_DESC_UPD_REG_PAGE123K_OFST &
++ FALCON_DMA_PAGE_MASK));
++
++ /* Check that the doorbells will be in the same page. */
++ EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST & PAGE_MASK) ==
++ (RX_DESC_UPD_REG_PAGE4_OFST & PAGE_MASK));
++
++ /* Check that the doorbells are in the same page. */
++ EFRM_ASSERT((tx_dma_page_addr & PAGE_MASK) ==
++ (rx_dma_page_addr & PAGE_MASK));
++
++ /* Check that the TX doorbell offset is correct. */
++ EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST & ~PAGE_MASK) ==
++ (tx_dma_page_addr & ~PAGE_MASK));
++
++ /* Check that the RX doorbell offset is correct. */
++ EFRM_ASSERT((RX_DESC_UPD_REG_PAGE4_OFST & ~PAGE_MASK) ==
++ (rx_dma_page_addr & ~PAGE_MASK));
++ }
++#endif
++
++ i = 0;
++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_TXDMAQ;
++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
++ hw_res_array[i].more_to_follow = 0;
++ hw_res_array[i].length = PAGE_SIZE;
++ hw_res_array[i].address =
++ (unsigned long)efx_state->vi_res->nic_info[ni].
++ dmaq_pages[EFRM_VI_RM_DMA_QUEUE_TX].kva;
++
++ i++;
++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_RXDMAQ;
++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
++ hw_res_array[i].more_to_follow = 0;
++ hw_res_array[i].length = PAGE_SIZE;
++ hw_res_array[i].address =
++ (unsigned long)efx_state->vi_res->nic_info[ni].
++ dmaq_pages[EFRM_VI_RM_DMA_QUEUE_RX].kva;
++
++ /* NB EFX_VI_HW_RESOURCE_TXBELL not used on Falcon */
++ /* NB EFX_VI_HW_RESOURCE_RXBELL not used on Falcon */
++
++ i++;
++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQTIMER;
++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
++ hw_res_array[i].more_to_follow = 0;
++ hw_res_array[i].length = PAGE_SIZE;
++ hw_res_array[i].address =
++ (unsigned long)phys + falcon_timer_page_addr(mdata->instance);
++
++ /* NB EFX_VI_HW_RESOURCE_EVQPTR not used on Falcon */
++
++ i++;
++ switch (efrm_nic_table.nic[ni]->devtype.variant) {
++ case 'A':
++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQRPTR;
++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
++ hw_res_array[i].more_to_follow = 0;
++ hw_res_array[i].length = PAGE_SIZE;
++ hw_res_array[i].address = (unsigned long)phys +
++ EVQ_RPTR_REG_OFST +
++ (FALCON_REGISTER128 * mdata->instance);
++ break;
++ case 'B':
++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET;
++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
++ hw_res_array[i].more_to_follow = 0;
++ hw_res_array[i].length = PAGE_SIZE;
++ hw_res_array[i].address =
++ (unsigned long)FALCON_EVQ_RPTR_REG_P0;
++ break;
++ default:
++ EFRM_ASSERT(0);
++ break;
++ }
++
++ i++;
++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQMEMKVA;
++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_IOBUFFER;
++ hw_res_array[i].more_to_follow = 0;
++ hw_res_array[i].length = PAGE_SIZE;
++ hw_res_array[i].address = (unsigned long)efx_state->vi_res->
++ nic_info[ni].evq_pages.iobuff.kva;
++
++ i++;
++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_BELLPAGE;
++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
++ hw_res_array[i].more_to_follow = 0;
++ hw_res_array[i].length = PAGE_SIZE;
++ hw_res_array[i].address =
++ (unsigned long)(phys +
++ falcon_tx_dma_page_addr(mdata->instance))
++ >> PAGE_SHIFT;
++
++ i++;
++
++ EFRM_ASSERT(i <= *length);
++
++ *length = i;
++
++ return 0;
++}
++EXPORT_SYMBOL(efx_vi_hw_resource_get_phys);
++#endif
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/eventq.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/eventq.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/eventq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/eventq.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,320 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains event queue support.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efhw/debug.h>
++#include <ci/efhw/iopage.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efhw/eventq.h>
++#include <ci/efhw/falcon.h>
++#include <ci/efhw/nic.h>
++
++#define KEVENTQ_MAGIC 0x07111974
++
++/*! Helper function to allocate the iobuffer needed by an eventq
++ * - it ensures the eventq has the correct alignment for the NIC
++ *
++ * \param rm Event-queue resource manager
++ * \param instance Event-queue instance (index)
++ * \param buf_bytes Requested size of eventq
++ * \return < 0 if iobuffer allocation fails
++ */
++int
++efhw_nic_event_queue_alloc_iobuffer(struct efhw_nic *nic,
++ struct eventq_resource_hardware *h,
++ int evq_instance, unsigned buf_bytes)
++{
++ unsigned int page_order;
++ int rc;
++
++ /* Allocate an iobuffer. */
++ page_order = get_order(buf_bytes);
++
++ h->iobuff_off = 0;
++
++ EFHW_TRACE("allocating eventq size %x",
++ 1u << (page_order + PAGE_SHIFT));
++ rc = efhw_iopages_alloc(nic, &h->iobuff, page_order);
++ if (rc < 0) {
++ EFHW_WARN("%s: failed to allocate %u pages",
++ __FUNCTION__, 1u << page_order);
++ return rc;
++ }
++
++ /* Set the eventq pages to match EFHW_CLEAR_EVENT() */
++ if (EFHW_CLEAR_EVENT_VALUE)
++ memset(efhw_iopages_ptr(&h->iobuff) + h->iobuff_off,
++ EFHW_CLEAR_EVENT_VALUE, (1u << page_order) * PAGE_SIZE);
++
++ EFHW_TRACE("%s: allocated %u pages", __FUNCTION__, 1u << (page_order));
++
++ /* For Falcon the NIC is programmed with the base buffer address of a
++ * contiguous region of buffer space. This means that larger than a
++ * PAGE event queues can be expected to allocate even when the host's
++ * physical memory is fragmented */
++ EFHW_ASSERT(efhw_nic_have_hw(nic));
++ EFHW_ASSERT(page_order <= h->buf_tbl_alloc.order);
++
++ /* Initialise the buffer table entries. */
++ falcon_nic_buffer_table_set_n(nic, h->buf_tbl_alloc.base,
++ efhw_iopages_dma_addr(&h->iobuff) +
++ h->iobuff_off, EFHW_NIC_PAGE_SIZE, 0,
++ 1 << page_order, 0);
++
++ if (evq_instance >= FALCON_EVQ_TBL_RESERVED)
++ falcon_nic_buffer_table_confirm(nic);
++ return 0;
++}
++
++/**********************************************************************
++ * Kernel event queue management.
++ */
++
++/* Values for [struct efhw_keventq::lock] field. */
++#define KEVQ_UNLOCKED 0
++#define KEVQ_LOCKED 1
++#define KEVQ_RECHECK 2
++
++int
++efhw_keventq_ctor(struct efhw_nic *nic, int instance,
++ struct efhw_keventq *evq,
++ struct efhw_ev_handler *ev_handlers)
++{
++ int rc;
++ unsigned buf_bytes = evq->hw.capacity * sizeof(efhw_event_t);
++
++ evq->instance = instance;
++ evq->ev_handlers = ev_handlers;
++
++ /* allocate an IObuffer for the eventq */
++ rc = efhw_nic_event_queue_alloc_iobuffer(nic, &evq->hw, evq->instance,
++ buf_bytes);
++ if (rc < 0)
++ return rc;
++
++ /* Zero the timer-value for this queue.
++ AND Tell the nic about the event queue. */
++ efhw_nic_event_queue_enable(nic, evq->instance, evq->hw.capacity,
++ efhw_iopages_dma_addr(&evq->hw.iobuff) +
++ evq->hw.iobuff_off,
++ evq->hw.buf_tbl_alloc.base);
++
++ evq->lock = KEVQ_UNLOCKED;
++ evq->evq_base = efhw_iopages_ptr(&evq->hw.iobuff) + evq->hw.iobuff_off;
++ evq->evq_ptr = 0;
++ evq->evq_mask = (evq->hw.capacity * sizeof(efhw_event_t)) - 1u;
++
++ EFHW_TRACE("%s: [%d] base=%p end=%p", __FUNCTION__, evq->instance,
++ evq->evq_base, evq->evq_base + buf_bytes);
++
++ return 0;
++}
++
++void efhw_keventq_dtor(struct efhw_nic *nic, struct efhw_keventq *evq)
++{
++ EFHW_ASSERT(evq);
++
++ EFHW_TRACE("%s: [%d]", __FUNCTION__, evq->instance);
++
++ /* Zero the timer-value for this queue.
++ And Tell NIC to stop using this event queue. */
++ efhw_nic_event_queue_disable(nic, evq->instance, 0);
++
++ /* free the pages used by the eventq itself */
++ efhw_iopages_free(nic, &evq->hw.iobuff);
++}
++
++void
++efhw_handle_txdmaq_flushed(struct efhw_nic *nic, struct efhw_ev_handler *h,
++ efhw_event_t *evp)
++{
++ int instance = (int)FALCON_EVENT_TX_FLUSH_Q_ID(evp);
++ EFHW_TRACE("%s: instance=%d", __FUNCTION__, instance);
++
++ if (!h->dmaq_flushed_fn) {
++ EFHW_WARN("%s: no handler registered", __FUNCTION__);
++ return;
++ }
++
++ h->dmaq_flushed_fn(nic, instance, false);
++}
++
++void
++efhw_handle_rxdmaq_flushed(struct efhw_nic *nic, struct efhw_ev_handler *h,
++ efhw_event_t *evp)
++{
++ int instance = (int)FALCON_EVENT_RX_FLUSH_Q_ID(evp);
++ EFHW_TRACE("%s: instance=%d", __FUNCTION__, instance);
++
++ if (!h->dmaq_flushed_fn) {
++ EFHW_WARN("%s: no handler registered", __FUNCTION__);
++ return;
++ }
++
++ h->dmaq_flushed_fn(nic, instance, true);
++}
++
++void
++efhw_handle_wakeup_event(struct efhw_nic *nic, struct efhw_ev_handler *h,
++ efhw_event_t *evp)
++{
++ if (!h->wakeup_fn) {
++ EFHW_WARN("%s: no handler registered", __FUNCTION__);
++ return;
++ }
++
++ h->wakeup_fn(nic, evp);
++}
++
++void
++efhw_handle_timeout_event(struct efhw_nic *nic, struct efhw_ev_handler *h,
++ efhw_event_t *evp)
++{
++ if (!h->timeout_fn) {
++ EFHW_WARN("%s: no handler registered", __FUNCTION__);
++ return;
++ }
++
++ h->timeout_fn(nic, evp);
++}
++
++/**********************************************************************
++ * Kernel event queue event handling.
++ */
++
++int efhw_keventq_poll(struct efhw_nic *nic, struct efhw_keventq *q)
++{
++ efhw_event_t *ev;
++ int l, count = 0;
++
++ EFHW_ASSERT(nic);
++ EFHW_ASSERT(q);
++ EFHW_ASSERT(q->ev_handlers);
++
++ /* Acquire the lock, or mark the queue as needing re-checking. */
++ for (;;) {
++ l = q->lock;
++ if (l == KEVQ_UNLOCKED) {
++ if ((int)cmpxchg(&q->lock, l, KEVQ_LOCKED) == l)
++ break;
++ } else if (l == KEVQ_LOCKED) {
++ if ((int)cmpxchg(&q->lock, l, KEVQ_RECHECK) == l)
++ return 0;
++ } else { /* already marked for re-checking */
++ EFHW_ASSERT(l == KEVQ_RECHECK);
++ return 0;
++ }
++ }
++
++ if (unlikely(EFHW_EVENT_OVERFLOW(q, q)))
++ goto overflow;
++
++ ev = EFHW_EVENT_PTR(q, q, 0);
++
++#ifndef NDEBUG
++ if (!EFHW_IS_EVENT(ev))
++ EFHW_TRACE("%s: %d NO EVENTS!", __FUNCTION__, q->instance);
++#endif
++
++ for (;;) {
++ /* Convention for return codes for handlers is:
++ ** 0 - no error, event consumed
++ ** 1 - no error, event not consumed
++ ** -ve - error, event not consumed
++ */
++ if (likely(EFHW_IS_EVENT(ev))) {
++ count++;
++
++ switch (FALCON_EVENT_CODE(ev)) {
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ case FALCON_EVENT_CODE_CHAR:
++ falcon_handle_char_event(nic, q->ev_handlers,
++ ev);
++ break;
++#endif
++
++ default:
++ EFHW_ERR("efhw_keventq_poll: [%d] UNEXPECTED "
++ "EVENT:"FALCON_EVENT_FMT,
++ q->instance,
++ FALCON_EVENT_PRI_ARG(*ev));
++ }
++
++ EFHW_CLEAR_EVENT(ev);
++ EFHW_EVENTQ_NEXT(q);
++
++ ev = EFHW_EVENT_PTR(q, q, 0);
++ } else {
++ /* No events left. Release the lock (checking if we
++ * need to re-poll to avoid race). */
++ l = q->lock;
++ if (l == KEVQ_LOCKED) {
++ if ((int)cmpxchg(&q->lock, l, KEVQ_UNLOCKED)
++ == l) {
++ EFHW_TRACE
++ ("efhw_keventq_poll: %d clean exit",
++ q->instance);
++ goto clean_exit;
++ }
++ }
++
++ /* Potentially more work to do. */
++ l = q->lock;
++ EFHW_ASSERT(l == KEVQ_RECHECK);
++ EFHW_TEST((int)cmpxchg(&q->lock, l, KEVQ_LOCKED) == l);
++ EFHW_TRACE("efhw_keventq_poll: %d re-poll required",
++ q->instance);
++ }
++ }
++
++ /* shouldn't get here */
++ EFHW_ASSERT(0);
++
++overflow:
++ /* ?? Oh dear. Should we poll everything that could have possibly
++ ** happened? Or merely cry out in anguish...
++ */
++ EFHW_WARN("efhw_keventq_poll: %d ***** OVERFLOW nic %d *****",
++ q->instance, nic->index);
++
++ q->lock = KEVQ_UNLOCKED;
++ return count;
++
++clean_exit:
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ /* Ack the processed events so that this event queue can potentially
++ raise interrupts again */
++ falcon_nic_evq_ack(nic, q->instance,
++ (EFHW_EVENT_OFFSET(q, q, 0) / sizeof(efhw_event_t)),
++ false);
++#endif
++ return count;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/falcon.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/falcon.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/falcon.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/falcon.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2758 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains Falcon hardware support.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/driver/efab/hardware.h>
++#include <ci/efhw/debug.h>
++#include <ci/efhw/iopage.h>
++#include <ci/efhw/falcon.h>
++#include <ci/efhw/falcon_hash.h>
++#include <ci/efhw/nic.h>
++#include <ci/efhw/eventq.h>
++#include <ci/efhw/checks.h>
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Workarounds and options
++ *
++ *---------------------------------------------------------------------------*/
++
++/* on for debug builds */
++#ifndef NDEBUG
++# define FALCON_FULL_FILTER_CACHE 1 /* complete SW shadow of filter tbl */
++# define FALCON_VERIFY_FILTERS 0
++#else /* Also adds duplicate filter check */
++# define FALCON_FULL_FILTER_CACHE 1 /* keep this on for some security */
++# define FALCON_VERIFY_FILTERS 0
++#endif
++
++/* options */
++#define RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL 8 /* default search limit */
++#define RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD 8 /* default search limit */
++#define RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL 8 /* default search limit */
++#define RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD 8 /* default search limit */
++#define RX_FILTER_CTL_SRCH_FUDGE_WILD 3 /* increase the search limit */
++#define RX_FILTER_CTL_SRCH_FUDGE_FULL 1 /* increase the search limit */
++
++#define FALCON_MAC_SET_TYPE_BY_SPEED 1
++
++/* FIXME: We should detect mode at runtime. */
++#define FALCON_BUFFER_TABLE_FULL_MODE 1
++
++/*----------------------------------------------------------------------------
++ *
++ * Debug Macros
++ *
++ *---------------------------------------------------------------------------*/
++
++#ifndef __KERNEL__
++#define _DEBUG_SYM_ extern
++#else
++#define _DEBUG_SYM_ static inline
++#endif
++
++ /*----------------------------------------------------------------------------
++ *
++ * Macros and forward declarations
++ *
++ *--------------------------------------------------------------------------*/
++
++#define FALCON_REGION_NUM 4 /* number of supported memory regions */
++
++#define FALCON_BUFFER_TBL_HALF_BYTES 4
++#define FALCON_BUFFER_TBL_FULL_BYTES 8
++
++/* Shadow buffer table - hack for testing only */
++#if FALCON_BUFFER_TABLE_FULL_MODE == 0
++# define FALCON_USE_SHADOW_BUFFER_TABLE 1
++#else
++# define FALCON_USE_SHADOW_BUFFER_TABLE 0
++#endif
++
++#if FALCON_USE_SHADOW_BUFFER_TABLE
++static uint64_t _falcon_buffer_table[FALCON_BUFFER_TBL_NUM];
++#endif
++
++/*----------------------------------------------------------------------------
++ *
++ * Header assertion checks
++ *
++ *---------------------------------------------------------------------------*/
++
++#define FALCON_ASSERT_VALID() /* nothing yet */
++
++/* Falcon has a 128bit register model but most registers have useful
++ defaults or only implement a small number of bits. Some registers
++ can be programmed 32bits UNLOCKED all others should be interlocked
++ against other threads within the same protection domain.
++
++ Aim is for software to perform the minimum number of writes and
++ also to minimise the read-modify-write activity (which generally
++ indicates a lack of clarity in the use model).
++
++ Registers which are programmed in this module are listed below
++ together with the method of access. Care must be taken to ensure
++ remain adequate if the register spec changes.
++
++ All 128bits programmed
++ FALCON_BUFFER_TBL_HALF
++ RX_FILTER_TBL
++ TX_DESC_PTR_TBL
++ RX_DESC_PTR_TBL
++ DRV_EV_REG
++
++ All 64bits programmed
++ FALCON_BUFFER_TBL_FULL
++
++ 32 bits are programmed (UNLOCKED)
++ EVQ_RPTR_REG
++
++ Low 64bits programmed remainder are written with a random number
++ RX_DC_CFG_REG
++ TX_DC_CFG_REG
++ SRM_RX_DC_CFG_REG
++ SRM_TX_DC_CFG_REG
++ BUF_TBL_CFG_REG
++ BUF_TBL_UPD_REG
++ SRM_UPD_EVQ_REG
++ EVQ_PTR_TBL
++ TIMER_CMD_REG
++ TX_PACE_TBL
++ FATAL_INTR_REG
++ INT_EN_REG (When enabling interrupts)
++ TX_FLUSH_DESCQ_REG
++ RX_FLUSH_DESCQ
++
++ Read Modify Write on low 32bits remainder are written with a random number
++ INT_EN_REG (When sending a driver interrupt)
++ DRIVER_REGX
++
++ Read Modify Write on low 64bits remainder are written with a random number
++ SRM_CFG_REG_OFST
++ RX_CFG_REG_OFST
++ RX_FILTER_CTL_REG
++
++ Read Modify Write on full 128bits
++ TXDP_RESERVED_REG (aka TXDP_UNDOCUMENTED)
++ TX_CFG_REG
++
++*/
++
++/*----------------------------------------------------------------------------
++ *
++ * Filters static data
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Defaults are set here to support dma.c */
++static unsigned tcp_full_srch_limit = RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL;
++static unsigned tcp_wild_srch_limit = RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD;
++static unsigned udp_full_srch_limit = RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL;
++static unsigned udp_wild_srch_limit = RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD;
++
++#if FALCON_VERIFY_FILTERS
++static void _falcon_nic_ipfilter_sanity(struct efhw_nic *nic);
++#endif
++
++/*----------------------------------------------------------------------------
++ *
++ * Filters low-level register interface
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Build the filter entry */
++static void
++_falcon_nic_ipfilter_build(struct efhw_nic *nic,
++ int tcp, int full, int rss_b0, int scat_b0,
++ uint filter_i, uint dmaq_id,
++ unsigned saddr_le32, unsigned sport_le16,
++ unsigned daddr_le32, unsigned dport_le16,
++ uint64_t *q0, uint64_t *q1)
++{
++ uint64_t v1, v2, v3, v4;
++ int type = tcp << 4 | full;
++
++ v4 = (((!tcp) << __DW4(TCP_UDP_1_LBN)) |
++ (dmaq_id << __DW4(RXQ_ID_1_LBN)));
++
++ switch (nic->devtype.variant) {
++ case 'A':
++ EFHW_ASSERT(!rss_b0);
++ break;
++ case 'B':
++ v4 |= scat_b0 << __DW4(SCATTER_EN_1_B0_LBN);
++ v4 |= rss_b0 << __DW4(RSS_EN_1_B0_LBN);
++ break;
++ default:
++ EFHW_ASSERT(0);
++ break;
++ }
++
++ v3 = daddr_le32;
++
++ switch (type) {
++
++ case 0x11: /* TCP_FULL */
++ case 0x01: /* UDP_FULL */
++ v2 = ((dport_le16 << __DW2(DEST_PORT_TCP_1_LBN)) |
++ (__HIGH(saddr_le32, SRC_IP_1_LBN, SRC_IP_1_WIDTH)));
++ v1 = ((__LOW(saddr_le32, SRC_IP_1_LBN, SRC_IP_1_WIDTH)) |
++ (sport_le16 << SRC_TCP_DEST_UDP_1_LBN));
++ break;
++
++ case 0x10: /* TCP_WILD */
++ v2 = ((uint64_t) dport_le16 << __DW2(DEST_PORT_TCP_1_LBN));
++ v1 = 0;
++ break;
++
++ case 0x00: /* UDP_WILD */
++ v2 = 0;
++ v1 = ((uint64_t) dport_le16 << SRC_TCP_DEST_UDP_0_LBN);
++ break;
++
++ default:
++ EFHW_ASSERT(0);
++ v2 = 0;
++ v1 = 0;
++ }
++
++ *q0 = (v2 << 32) | v1;
++ *q1 = (v4 << 32) | v3;
++}
++
++static void
++_falcon_nic_ipfilter_set(struct efhw_nic *nic, int tcp,
++ int full, int rss_b0, int scat_b0,
++ uint filter_i, uint dmaq_id,
++ unsigned saddr_le32, unsigned sport_le16,
++ unsigned daddr_le32, unsigned dport_le16)
++{
++ uint64_t q0, q1;
++
++ /* wish you wouldn't do this */
++ EFHW_BUILD_ASSERT(RX_FILTER_TBL1_OFST ==
++ RX_FILTER_TBL0_OFST + FALCON_REGISTER128);
++ EFHW_BUILD_ASSERT(TCP_UDP_1_LBN == TCP_UDP_0_LBN);
++ EFHW_BUILD_ASSERT(RXQ_ID_1_LBN == RXQ_ID_0_LBN);
++ EFHW_BUILD_ASSERT(DEST_IP_1_LBN == DEST_IP_0_LBN);
++ EFHW_BUILD_ASSERT(DEST_PORT_TCP_1_LBN == DEST_PORT_TCP_0_LBN);
++ EFHW_BUILD_ASSERT(SRC_IP_1_LBN == SRC_IP_0_LBN);
++ EFHW_BUILD_ASSERT(SRC_TCP_DEST_UDP_1_LBN == SRC_TCP_DEST_UDP_0_LBN);
++ EFHW_BUILD_ASSERT(SCATTER_EN_1_B0_LBN == SCATTER_EN_0_B0_LBN);
++ EFHW_BUILD_ASSERT(RSS_EN_1_B0_LBN == RSS_EN_0_B0_LBN);
++
++ EFHW_BUILD_ASSERT(TCP_UDP_1_WIDTH == TCP_UDP_0_WIDTH);
++ EFHW_BUILD_ASSERT(RXQ_ID_1_WIDTH == RXQ_ID_0_WIDTH);
++ EFHW_BUILD_ASSERT(DEST_IP_1_WIDTH == DEST_IP_0_WIDTH);
++ EFHW_BUILD_ASSERT(DEST_PORT_TCP_1_WIDTH == DEST_PORT_TCP_0_WIDTH);
++ EFHW_BUILD_ASSERT(SRC_IP_1_WIDTH == SRC_IP_0_WIDTH);
++ EFHW_BUILD_ASSERT(SRC_TCP_DEST_UDP_1_WIDTH == SRC_TCP_DEST_UDP_0_WIDTH);
++ EFHW_BUILD_ASSERT(SCATTER_EN_1_B0_WIDTH == SCATTER_EN_0_B0_WIDTH);
++ EFHW_BUILD_ASSERT(RSS_EN_1_B0_WIDTH == RSS_EN_0_B0_WIDTH);
++
++ /* TODO: Use filter table 1 as well */
++ ulong offset = RX_FILTER_TBL0_OFST + filter_i * 2 * FALCON_REGISTER128;
++
++ EFHW_TRACE("%s[%x]: offset=%lx", __FUNCTION__, filter_i, offset);
++
++ EFHW_TRACE("%s[%x]: filter %d tcp %d full %d src=%x:%x dest=%x:%x%s%s",
++ __FUNCTION__, filter_i, tcp, full, dmaq_id,
++ saddr_le32, sport_le16, daddr_le32, dport_le16,
++ rss_b0 ? " RSS" : "", scat_b0 ? " SCAT" : "");
++
++ EFHW_ASSERT(filter_i < nic->filter_tbl_size);
++
++ /* dword 4 */
++ __DW4CHCK(TCP_UDP_1_LBN, TCP_UDP_1_WIDTH);
++ __DW4CHCK(RXQ_ID_1_LBN, RXQ_ID_1_WIDTH);
++
++ __RANGECHCK(tcp, TCP_UDP_1_WIDTH);
++ __RANGECHCK(dmaq_id, RXQ_ID_1_WIDTH);
++
++ /* dword 3 */
++ __DW3CHCK(DEST_IP_1_LBN, DEST_IP_1_WIDTH);
++ __RANGECHCK(daddr_le32, DEST_IP_1_WIDTH);
++
++ /* dword 2 */
++ __DW2CHCK(DEST_PORT_TCP_1_LBN, DEST_PORT_TCP_1_WIDTH);
++ __LWCHK(SRC_IP_1_LBN, SRC_IP_1_WIDTH);
++ __RANGECHCK(saddr_le32, SRC_IP_1_WIDTH);
++
++ /* dword 1 */
++ __DWCHCK(SRC_TCP_DEST_UDP_1_LBN, SRC_TCP_DEST_UDP_1_WIDTH);
++ __RANGECHCK(sport_le16, SRC_TCP_DEST_UDP_1_WIDTH);
++ __RANGECHCK(dport_le16, SRC_TCP_DEST_UDP_1_WIDTH);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ _falcon_nic_ipfilter_build(nic, tcp, full, rss_b0, scat_b0,
++ filter_i, dmaq_id, saddr_le32, sport_le16,
++ daddr_le32, dport_le16, &q0, &q1);
++
++ EFHW_TRACE("%s[%x]@%p+%lx: %" PRIx64 " %" PRIx64, __FUNCTION__,
++ filter_i, EFHW_KVA(nic), offset, q0, q1);
++
++ falcon_write_qq(EFHW_KVA(nic) + offset, q0, q1);
++ mmiowb();
++
++#if FALCON_VERIFY_FILTERS
++ {
++ uint64_t q0read, q1read;
++
++ /* Read a different entry first - entry BIU flushed shadow */
++ falcon_read_qq(EFHW_KVA(nic) + offset+0x10, &q0read, &q1read);
++ falcon_read_qq(EFHW_KVA(nic) + offset, &q0read, &q1read);
++ EFHW_ASSERT(q0read == q0);
++ EFHW_ASSERT(q1read == q1);
++
++ _falcon_nic_ipfilter_sanity(nic);
++ }
++#endif
++}
++
++static void _falcon_nic_ipfilter_clear(struct efhw_nic *nic, uint filter_i)
++{
++ /* TODO: Use filter table 1 as well */
++ ulong offset = RX_FILTER_TBL0_OFST + filter_i * 2 * FALCON_REGISTER128;
++
++ EFHW_ASSERT(filter_i < nic->filter_tbl_size);
++
++ EFHW_TRACE("%s[%x]", __FUNCTION__, filter_i);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ falcon_write_qq(EFHW_KVA(nic) + offset, 0, 0);
++ mmiowb();
++#if FALCON_VERIFY_FILTERS
++ {
++ uint64_t q0read, q1read;
++
++ /* Read a different entry first - entry BIU flushed shadow */
++ falcon_read_qq(EFHW_KVA(nic) + offset+0x10, &q0read, &q1read);
++ falcon_read_qq(EFHW_KVA(nic) + offset, &q0read, &q1read);
++ EFHW_ASSERT(q0read == 0);
++ EFHW_ASSERT(q1read == 0);
++
++ _falcon_nic_ipfilter_sanity(nic);
++ }
++#endif
++}
++
++/*----------------------------------------------------------------------------
++ *
++ * DMAQ low-level register interface
++ *
++ *---------------------------------------------------------------------------*/
++
++static unsigned dmaq_sizes[] = {
++ 512,
++ EFHW_1K,
++ EFHW_2K,
++ EFHW_4K,
++};
++
++#define N_DMAQ_SIZES (sizeof(dmaq_sizes) / sizeof(dmaq_sizes[0]))
++
++static inline ulong falcon_dma_tx_q_offset(struct efhw_nic *nic, unsigned dmaq)
++{
++ EFHW_ASSERT(dmaq < FALCON_DMAQ_NUM);
++ return TX_DESC_PTR_TBL_OFST + dmaq * FALCON_REGISTER128;
++}
++
++static inline uint falcon_dma_tx_q_size_index(uint dmaq_size)
++{
++ uint i;
++
++ /* size must be one of the various options, otherwise we assert */
++ for (i = 0; i < N_DMAQ_SIZES; i++) {
++ if (dmaq_size == dmaq_sizes[i])
++ break;
++ }
++ EFHW_ASSERT(i < N_DMAQ_SIZES);
++ return i;
++}
++
++static void
++falcon_dmaq_tx_q_init(struct efhw_nic *nic,
++ uint dmaq, uint evq_id, uint own_id,
++ uint tag, uint dmaq_size, uint buf_idx, uint flags)
++{
++ FALCON_LOCK_DECL;
++ uint index, desc_type;
++ uint64_t val1, val2, val3;
++ ulong offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ /* Q attributes */
++ int iscsi_hdig_en = ((flags & EFHW_VI_ISCSI_TX_HDIG_EN) != 0);
++ int iscsi_ddig_en = ((flags & EFHW_VI_ISCSI_TX_DDIG_EN) != 0);
++ int csum_ip_dis = ((flags & EFHW_VI_TX_IP_CSUM_DIS) != 0);
++ int csum_tcp_dis = ((flags & EFHW_VI_TX_TCPUDP_CSUM_DIS) != 0);
++ int non_ip_drop_dis = ((flags & EFHW_VI_TX_TCPUDP_ONLY) == 0);
++
++ /* initialise the TX descriptor queue pointer table */
++
++ /* NB physical vs buffer addressing is determined by the Queue ID. */
++
++ offset = falcon_dma_tx_q_offset(nic, dmaq);
++ index = falcon_dma_tx_q_size_index(dmaq_size);
++
++ /* allow VI flag to override this queue's descriptor type */
++ desc_type = (flags & EFHW_VI_TX_PHYS_ADDR_EN) ? 0 : 1;
++
++ /* bug9403: It is dangerous to allow buffer-addressed queues to
++ * have owner_id=0. */
++ EFHW_ASSERT((own_id > 0) || desc_type == 0);
++
++ /* dword 1 */
++ __DWCHCK(TX_DESCQ_FLUSH_LBN, TX_DESCQ_FLUSH_WIDTH);
++ __DWCHCK(TX_DESCQ_TYPE_LBN, TX_DESCQ_TYPE_WIDTH);
++ __DWCHCK(TX_DESCQ_SIZE_LBN, TX_DESCQ_SIZE_WIDTH);
++ __DWCHCK(TX_DESCQ_LABEL_LBN, TX_DESCQ_LABEL_WIDTH);
++ __DWCHCK(TX_DESCQ_OWNER_ID_LBN, TX_DESCQ_OWNER_ID_WIDTH);
++
++ __LWCHK(TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH);
++
++ __RANGECHCK(1, TX_DESCQ_FLUSH_WIDTH);
++ __RANGECHCK(desc_type, TX_DESCQ_TYPE_WIDTH);
++ __RANGECHCK(index, TX_DESCQ_SIZE_WIDTH);
++ __RANGECHCK(tag, TX_DESCQ_LABEL_WIDTH);
++ __RANGECHCK(own_id, TX_DESCQ_OWNER_ID_WIDTH);
++ __RANGECHCK(evq_id, TX_DESCQ_EVQ_ID_WIDTH);
++
++ val1 = ((desc_type << TX_DESCQ_TYPE_LBN) |
++ (index << TX_DESCQ_SIZE_LBN) |
++ (tag << TX_DESCQ_LABEL_LBN) |
++ (own_id << TX_DESCQ_OWNER_ID_LBN) |
++ (__LOW(evq_id, TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH)));
++
++ /* dword 2 */
++ __DW2CHCK(TX_DESCQ_BUF_BASE_ID_LBN, TX_DESCQ_BUF_BASE_ID_WIDTH);
++ __RANGECHCK(buf_idx, TX_DESCQ_BUF_BASE_ID_WIDTH);
++
++ val2 = ((__HIGH(evq_id, TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH)) |
++ (buf_idx << __DW2(TX_DESCQ_BUF_BASE_ID_LBN)));
++
++ /* dword 3 */
++ __DW3CHCK(TX_ISCSI_HDIG_EN_LBN, TX_ISCSI_HDIG_EN_WIDTH);
++ __DW3CHCK(TX_ISCSI_DDIG_EN_LBN, TX_ISCSI_DDIG_EN_WIDTH);
++ __RANGECHCK(iscsi_hdig_en, TX_ISCSI_HDIG_EN_WIDTH);
++ __RANGECHCK(iscsi_ddig_en, TX_ISCSI_DDIG_EN_WIDTH);
++
++ val3 = ((iscsi_hdig_en << __DW3(TX_ISCSI_HDIG_EN_LBN)) |
++ (iscsi_ddig_en << __DW3(TX_ISCSI_DDIG_EN_LBN)) |
++ (1 << __DW3(TX_DESCQ_EN_LBN))); /* queue enable bit */
++
++ switch (nic->devtype.variant) {
++ case 'B':
++ __DW3CHCK(TX_NON_IP_DROP_DIS_B0_LBN,
++ TX_NON_IP_DROP_DIS_B0_WIDTH);
++ __DW3CHCK(TX_IP_CHKSM_DIS_B0_LBN, TX_IP_CHKSM_DIS_B0_WIDTH);
++ __DW3CHCK(TX_TCP_CHKSM_DIS_B0_LBN, TX_TCP_CHKSM_DIS_B0_WIDTH);
++
++ val3 |= ((non_ip_drop_dis << __DW3(TX_NON_IP_DROP_DIS_B0_LBN))|
++ (csum_ip_dis << __DW3(TX_IP_CHKSM_DIS_B0_LBN)) |
++ (csum_tcp_dis << __DW3(TX_TCP_CHKSM_DIS_B0_LBN)));
++ break;
++ case 'A':
++ if (csum_ip_dis || csum_tcp_dis || !non_ip_drop_dis)
++ EFHW_WARN
++ ("%s: bad settings for A1 csum_ip_dis=%d "
++ "csum_tcp_dis=%d non_ip_drop_dis=%d",
++ __FUNCTION__, csum_ip_dis,
++ csum_tcp_dis, non_ip_drop_dis);
++ break;
++ default:
++ EFHW_ASSERT(0);
++ break;
++ }
++
++ EFHW_TRACE("%s: txq %x evq %u tag %x id %x buf %x "
++ "%x:%x:%x->%" PRIx64 ":%" PRIx64 ":%" PRIx64,
++ __FUNCTION__,
++ dmaq, evq_id, tag, own_id, buf_idx, dmaq_size,
++ iscsi_hdig_en, iscsi_ddig_en, val1, val2, val3);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++ return;
++}
++
++static inline ulong
++falcon_dma_rx_q_offset(struct efhw_nic *nic, unsigned dmaq)
++{
++ EFHW_ASSERT(dmaq < FALCON_DMAQ_NUM);
++ return RX_DESC_PTR_TBL_OFST + dmaq * FALCON_REGISTER128;
++}
++
++static void
++falcon_dmaq_rx_q_init(struct efhw_nic *nic,
++ uint dmaq, uint evq_id, uint own_id,
++ uint tag, uint dmaq_size, uint buf_idx, uint flags)
++{
++ FALCON_LOCK_DECL;
++ uint i, desc_type = 1;
++ uint64_t val1, val2, val3;
++ ulong offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ /* Q attributes */
++#if BUG5762_WORKAROUND
++ int jumbo = 1; /* Queues must not have mixed types */
++#else
++ int jumbo = ((flags & EFHW_VI_JUMBO_EN) != 0);
++#endif
++ int iscsi_hdig_en = ((flags & EFHW_VI_ISCSI_RX_HDIG_EN) != 0);
++ int iscsi_ddig_en = ((flags & EFHW_VI_ISCSI_RX_DDIG_EN) != 0);
++
++ /* initialise the TX descriptor queue pointer table */
++ offset = falcon_dma_rx_q_offset(nic, dmaq);
++
++ /* size must be one of the various options, otherwise we assert */
++ for (i = 0; i < N_DMAQ_SIZES; i++) {
++ if (dmaq_size == dmaq_sizes[i])
++ break;
++ }
++ EFHW_ASSERT(i < N_DMAQ_SIZES);
++
++ /* allow VI flag to override this queue's descriptor type */
++ desc_type = (flags & EFHW_VI_RX_PHYS_ADDR_EN) ? 0 : 1;
++
++ /* bug9403: It is dangerous to allow buffer-addressed queues to have
++ * owner_id=0 */
++ EFHW_ASSERT((own_id > 0) || desc_type == 0);
++
++ /* dword 1 */
++ __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH);
++ __DWCHCK(RX_DESCQ_JUMBO_LBN, RX_DESCQ_JUMBO_WIDTH);
++ __DWCHCK(RX_DESCQ_TYPE_LBN, RX_DESCQ_TYPE_WIDTH);
++ __DWCHCK(RX_DESCQ_SIZE_LBN, RX_DESCQ_SIZE_WIDTH);
++ __DWCHCK(RX_DESCQ_LABEL_LBN, RX_DESCQ_LABEL_WIDTH);
++ __DWCHCK(RX_DESCQ_OWNER_ID_LBN, RX_DESCQ_OWNER_ID_WIDTH);
++
++ __LWCHK(RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH);
++
++ __RANGECHCK(1, RX_DESCQ_EN_WIDTH);
++ __RANGECHCK(jumbo, RX_DESCQ_JUMBO_WIDTH);
++ __RANGECHCK(desc_type, RX_DESCQ_TYPE_WIDTH);
++ __RANGECHCK(i, RX_DESCQ_SIZE_WIDTH);
++ __RANGECHCK(tag, RX_DESCQ_LABEL_WIDTH);
++ __RANGECHCK(own_id, RX_DESCQ_OWNER_ID_WIDTH);
++ __RANGECHCK(evq_id, RX_DESCQ_EVQ_ID_WIDTH);
++
++ val1 = ((1 << RX_DESCQ_EN_LBN) |
++ (jumbo << RX_DESCQ_JUMBO_LBN) |
++ (desc_type << RX_DESCQ_TYPE_LBN) |
++ (i << RX_DESCQ_SIZE_LBN) |
++ (tag << RX_DESCQ_LABEL_LBN) |
++ (own_id << RX_DESCQ_OWNER_ID_LBN) |
++ (__LOW(evq_id, RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH)));
++
++ /* dword 2 */
++ __DW2CHCK(RX_DESCQ_BUF_BASE_ID_LBN, RX_DESCQ_BUF_BASE_ID_WIDTH);
++ __RANGECHCK(buf_idx, RX_DESCQ_BUF_BASE_ID_WIDTH);
++
++ val2 = ((__HIGH(evq_id, RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH)) |
++ (buf_idx << __DW2(RX_DESCQ_BUF_BASE_ID_LBN)));
++
++ /* dword 3 */
++ __DW3CHCK(RX_ISCSI_HDIG_EN_LBN, RX_ISCSI_HDIG_EN_WIDTH);
++ __DW3CHCK(RX_ISCSI_DDIG_EN_LBN, RX_ISCSI_DDIG_EN_WIDTH);
++ __RANGECHCK(iscsi_hdig_en, RX_ISCSI_HDIG_EN_WIDTH);
++ __RANGECHCK(iscsi_ddig_en, RX_ISCSI_DDIG_EN_WIDTH);
++
++ val3 = (iscsi_hdig_en << __DW3(RX_ISCSI_HDIG_EN_LBN)) |
++ (iscsi_ddig_en << __DW3(RX_ISCSI_DDIG_EN_LBN));
++
++ EFHW_TRACE("%s: rxq %x evq %u tag %x id %x buf %x %s "
++ "%x:%x:%x -> %" PRIx64 ":%" PRIx64 ":%" PRIx64,
++ __FUNCTION__,
++ dmaq, evq_id, tag, own_id, buf_idx,
++ jumbo ? "jumbo" : "normal", dmaq_size,
++ iscsi_hdig_en, iscsi_ddig_en, val1, val2, val3);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++ return;
++}
++
++static void falcon_dmaq_tx_q_disable(struct efhw_nic *nic, uint dmaq)
++{
++ FALCON_LOCK_DECL;
++ uint64_t val1, val2, val3;
++ ulong offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ /* initialise the TX descriptor queue pointer table */
++
++ offset = falcon_dma_tx_q_offset(nic, dmaq);
++
++ /* dword 1 */
++ __DWCHCK(TX_DESCQ_TYPE_LBN, TX_DESCQ_TYPE_WIDTH);
++
++ val1 = ((uint64_t) 1 << TX_DESCQ_TYPE_LBN);
++
++ /* dword 2 */
++ val2 = 0;
++
++ /* dword 3 */
++ val3 = (0 << __DW3(TX_DESCQ_EN_LBN)); /* queue enable bit */
++
++ EFHW_TRACE("%s: %x->%" PRIx64 ":%" PRIx64 ":%" PRIx64,
++ __FUNCTION__, dmaq, val1, val2, val3);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++ return;
++}
++
++static void falcon_dmaq_rx_q_disable(struct efhw_nic *nic, uint dmaq)
++{
++ FALCON_LOCK_DECL;
++ uint64_t val1, val2, val3;
++ ulong offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ /* initialise the TX descriptor queue pointer table */
++ offset = falcon_dma_rx_q_offset(nic, dmaq);
++
++ /* dword 1 */
++ __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH);
++ __DWCHCK(RX_DESCQ_TYPE_LBN, RX_DESCQ_TYPE_WIDTH);
++
++ val1 = ((0 << RX_DESCQ_EN_LBN) | (1 << RX_DESCQ_TYPE_LBN));
++
++ /* dword 2 */
++ val2 = 0;
++
++ /* dword 3 */
++ val3 = 0;
++
++ EFHW_TRACE("falcon_dmaq_rx_q_disable: %x->%"
++ PRIx64 ":%" PRIx64 ":%" PRIx64,
++ dmaq, val1, val2, val3);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++ return;
++}
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Buffer Table low-level register interface
++ *
++ *---------------------------------------------------------------------------*/
++
++/*! Convert a (potentially) 64-bit physical address to 32-bits. Every use
++** of this function is a place where we're not 64-bit clean.
++*/
++static inline uint32_t dma_addr_to_u32(dma_addr_t addr)
++{
++ /* Top bits had better be zero! */
++ EFHW_ASSERT(addr == (addr & 0xffffffff));
++ return (uint32_t) addr;
++}
++
++static inline uint32_t
++falcon_nic_buffer_table_entry32_mk(dma_addr_t dma_addr, int own_id)
++{
++ uint32_t dma_addr32 = FALCON_BUFFER_4K_PAGE(dma_addr_to_u32(dma_addr));
++
++ /* don't do this to me */
++ EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_LBN == BUF_ADR_HBUF_EVEN_LBN + 32);
++ EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_LBN ==
++ BUF_OWNER_ID_HBUF_EVEN_LBN + 32);
++
++ EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_WIDTH ==
++ BUF_OWNER_ID_HBUF_EVEN_WIDTH);
++ EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_WIDTH == BUF_ADR_HBUF_EVEN_WIDTH);
++
++ __DWCHCK(BUF_ADR_HBUF_EVEN_LBN, BUF_ADR_HBUF_EVEN_WIDTH);
++ __DWCHCK(BUF_OWNER_ID_HBUF_EVEN_LBN, BUF_OWNER_ID_HBUF_EVEN_WIDTH);
++
++ __RANGECHCK(dma_addr32, BUF_ADR_HBUF_EVEN_WIDTH);
++ __RANGECHCK(own_id, BUF_OWNER_ID_HBUF_EVEN_WIDTH);
++
++ return ((dma_addr32 << BUF_ADR_HBUF_EVEN_LBN) |
++ (own_id << BUF_OWNER_ID_HBUF_EVEN_LBN));
++}
++
++static inline uint64_t
++falcon_nic_buffer_table_entry64_mk(dma_addr_t dma_addr,
++ int bufsz, /* bytes */
++ int region, int own_id)
++{
++ __DW2CHCK(IP_DAT_BUF_SIZE_LBN, IP_DAT_BUF_SIZE_WIDTH);
++ __DW2CHCK(BUF_ADR_REGION_LBN, BUF_ADR_REGION_WIDTH);
++ __LWCHK(BUF_ADR_FBUF_LBN, BUF_ADR_FBUF_WIDTH);
++ __DWCHCK(BUF_OWNER_ID_FBUF_LBN, BUF_OWNER_ID_FBUF_WIDTH);
++
++ EFHW_ASSERT((bufsz == EFHW_4K) || (bufsz == EFHW_8K));
++
++ dma_addr = (dma_addr >> 12) & __FALCON_MASK64(BUF_ADR_FBUF_WIDTH);
++
++ __RANGECHCK(dma_addr, BUF_ADR_FBUF_WIDTH);
++ __RANGECHCK(1, IP_DAT_BUF_SIZE_WIDTH);
++ __RANGECHCK(region, BUF_ADR_REGION_WIDTH);
++ __RANGECHCK(own_id, BUF_OWNER_ID_FBUF_WIDTH);
++
++ return (((uint64_t) (bufsz == EFHW_8K) << IP_DAT_BUF_SIZE_LBN) |
++ ((uint64_t) region << BUF_ADR_REGION_LBN) |
++ ((uint64_t) dma_addr << BUF_ADR_FBUF_LBN) |
++ ((uint64_t) own_id << BUF_OWNER_ID_FBUF_LBN));
++}
++
++static inline void
++_falcon_nic_buffer_table_set32(struct efhw_nic *nic,
++ dma_addr_t dma_addr, uint bufsz,
++ uint region, /* not used */
++ int own_id, int buffer_id)
++{
++ /* programming the half table needs to be done in pairs. */
++ uint64_t entry, val, shift;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ efhw_ioaddr_t offset;
++
++ EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_LBN == BUF_ADR_HBUF_EVEN_LBN + 32);
++ EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_LBN ==
++ BUF_OWNER_ID_HBUF_EVEN_LBN + 32);
++
++ shift = (buffer_id & 1) ? 32 : 0;
++
++ offset = (efhw_kva + BUF_HALF_TBL_OFST +
++ ((buffer_id & ~1) * FALCON_BUFFER_TBL_HALF_BYTES));
++
++ entry = falcon_nic_buffer_table_entry32_mk(dma_addr_to_u32(dma_addr),
++ own_id);
++
++#if FALCON_USE_SHADOW_BUFFER_TABLE
++ val = _falcon_buffer_table[buffer_id & ~1];
++#else
++ /* This will not work unless we've completed
++ * the buffer table updates */
++ falcon_read_q(offset, &val);
++#endif
++ val &= ~(((uint64_t) 0xffffffff) << shift);
++ val |= (entry << shift);
++
++ EFHW_TRACE("%s[%x]: " ci_dma_addr_fmt ":%x:%" PRIx64 "->%x = %"
++ PRIx64, __FUNCTION__, buffer_id, dma_addr, own_id, entry,
++ (unsigned)(offset - efhw_kva), val);
++
++ /* Falcon requires that access to this register is serialised */
++ falcon_write_q(offset, val);
++
++ /* NB. No mmiowb(). Caller should do that e.g by calling commit */
++
++#if FALCON_USE_SHADOW_BUFFER_TABLE
++ _falcon_buffer_table[buffer_id & ~1] = val;
++#endif
++
++ /* Confirm the entry if the event queues haven't been set up. */
++ if (!nic->irq_handler) {
++ uint64_t new_val;
++ int count = 0;
++ while (1) {
++ mmiowb();
++ falcon_read_q(offset, &new_val);
++ if (new_val == val)
++ break;
++ count++;
++ if (count > 1000) {
++ EFHW_WARN("%s: poll Timeout", __FUNCTION__);
++ break;
++ }
++ udelay(1);
++ }
++ }
++}
++
++static inline void
++_falcon_nic_buffer_table_set64(struct efhw_nic *nic,
++ dma_addr_t dma_addr, uint bufsz,
++ uint region, int own_id, int buffer_id)
++{
++ efhw_ioaddr_t offset;
++ uint64_t entry;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ EFHW_ASSERT(region < FALCON_REGION_NUM);
++
++ EFHW_ASSERT((bufsz == EFHW_4K) ||
++ (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE));
++
++ offset = (efhw_kva + BUF_FULL_TBL_OFST +
++ (buffer_id * FALCON_BUFFER_TBL_FULL_BYTES));
++
++ entry = falcon_nic_buffer_table_entry64_mk(dma_addr, bufsz, region,
++ own_id);
++
++ EFHW_TRACE("%s[%x]: " ci_dma_addr_fmt
++ ":bufsz=%x:region=%x:ownid=%x",
++ __FUNCTION__, buffer_id, dma_addr, bufsz, region, own_id);
++
++ EFHW_TRACE("%s: BUF[%x]:NIC[%x]->%" PRIx64,
++ __FUNCTION__, buffer_id,
++ (unsigned int)(offset - efhw_kva), entry);
++
++ /* Falcon requires that access to this register is serialised */
++ falcon_write_q(offset, entry);
++
++ /* NB. No mmiowb(). Caller should do that e.g by calling commit */
++
++ /* Confirm the entry if the event queues haven't been set up. */
++ if (!nic->irq_handler) {
++ uint64_t new_entry;
++ int count = 0;
++ while (1) {
++ mmiowb();
++ falcon_read_q(offset, &new_entry);
++ if (new_entry == entry)
++ return;
++ count++;
++ if (count > 1000) {
++ EFHW_WARN("%s: poll Timeout waiting for "
++ "value %"PRIx64
++ " (last was %"PRIx64")",
++ __FUNCTION__, entry, new_entry);
++ break;
++ }
++ udelay(1);
++ }
++ }
++}
++
++#if FALCON_BUFFER_TABLE_FULL_MODE
++#define _falcon_nic_buffer_table_set _falcon_nic_buffer_table_set64
++#else
++#define _falcon_nic_buffer_table_set _falcon_nic_buffer_table_set32
++#endif
++
++static inline void _falcon_nic_buffer_table_commit(struct efhw_nic *nic)
++{
++ /* MUST be called holding the FALCON_LOCK */
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ uint64_t cmd;
++
++ EFHW_BUILD_ASSERT(BUF_TBL_UPD_REG_KER_OFST == BUF_TBL_UPD_REG_OFST);
++
++ __DW2CHCK(BUF_UPD_CMD_LBN, BUF_UPD_CMD_WIDTH);
++ __RANGECHCK(1, BUF_UPD_CMD_WIDTH);
++
++ cmd = ((uint64_t) 1 << BUF_UPD_CMD_LBN);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ falcon_write_qq(efhw_kva + BUF_TBL_UPD_REG_OFST,
++ cmd, FALCON_ATOMIC_UPD_REG);
++ mmiowb();
++
++ nic->buf_commit_outstanding++;
++ EFHW_TRACE("COMMIT REQ out=%d", nic->buf_commit_outstanding);
++}
++
++static void falcon_nic_buffer_table_commit(struct efhw_nic *nic)
++{
++ /* nothing to do */
++}
++
++static inline void
++_falcon_nic_buffer_table_clear(struct efhw_nic *nic, int buffer_id, int num)
++{
++ uint64_t cmd;
++ uint64_t start_id = buffer_id;
++ uint64_t end_id = buffer_id + num - 1;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ efhw_ioaddr_t offset = (efhw_kva + BUF_TBL_UPD_REG_OFST);
++
++ EFHW_BUILD_ASSERT(BUF_TBL_UPD_REG_KER_OFST == BUF_TBL_UPD_REG_OFST);
++
++#if !FALCON_BUFFER_TABLE_FULL_MODE
++ /* buffer_ids in half buffer mode reference pairs of buffers */
++ EFHW_ASSERT(buffer_id % 1 == 0);
++ EFHW_ASSERT(num % 1 == 0);
++ start_id = start_id >> 1;
++ end_id = end_id >> 1;
++#endif
++
++ EFHW_ASSERT(num >= 1);
++
++ __DWCHCK(BUF_CLR_START_ID_LBN, BUF_CLR_START_ID_WIDTH);
++ __DW2CHCK(BUF_CLR_END_ID_LBN, BUF_CLR_END_ID_WIDTH);
++
++ __DW2CHCK(BUF_CLR_CMD_LBN, BUF_CLR_CMD_WIDTH);
++ __RANGECHCK(1, BUF_CLR_CMD_WIDTH);
++
++ __RANGECHCK(start_id, BUF_CLR_START_ID_WIDTH);
++ __RANGECHCK(end_id, BUF_CLR_END_ID_WIDTH);
++
++ cmd = (((uint64_t) 1 << BUF_CLR_CMD_LBN) |
++ (start_id << BUF_CLR_START_ID_LBN) |
++ (end_id << BUF_CLR_END_ID_LBN));
++
++ /* Falcon requires 128 bit atomic access for this register */
++ falcon_write_qq(offset, cmd, FALCON_ATOMIC_UPD_REG);
++ mmiowb();
++
++ nic->buf_commit_outstanding++;
++ EFHW_TRACE("COMMIT CLEAR out=%d", nic->buf_commit_outstanding);
++}
++
++/*----------------------------------------------------------------------------
++ *
++ * Events low-level register interface
++ *
++ *---------------------------------------------------------------------------*/
++
++static unsigned eventq_sizes[] = {
++ 512,
++ EFHW_1K,
++ EFHW_2K,
++ EFHW_4K,
++ EFHW_8K,
++ EFHW_16K,
++ EFHW_32K
++};
++
++#define N_EVENTQ_SIZES (sizeof(eventq_sizes) / sizeof(eventq_sizes[0]))
++
++static inline void falcon_nic_srm_upd_evq(struct efhw_nic *nic, int evq)
++{
++ /* set up the eventq which will receive events from the SRAM module.
++ * i.e buffer table updates and clears, TX and RX aperture table
++ * updates */
++
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ EFHW_BUILD_ASSERT(SRM_UPD_EVQ_REG_OFST == SRM_UPD_EVQ_REG_KER_OFST);
++
++ EFHW_ASSERT((evq == FALCON_EVQ_KERNEL0) || (evq == FALCON_EVQ_CHAR) ||
++ (evq == FALCON_EVQ_NONIRQ));
++
++ __DWCHCK(SRM_UPD_EVQ_ID_LBN, SRM_UPD_EVQ_ID_WIDTH);
++ __RANGECHCK(evq, SRM_UPD_EVQ_ID_WIDTH);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + SRM_UPD_EVQ_REG_OFST,
++ ((uint64_t) evq << SRM_UPD_EVQ_ID_LBN),
++ FALCON_ATOMIC_SRPM_UDP_EVQ_REG);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++static inline void
++falcon_nic_evq_ptr_tbl(struct efhw_nic *nic,
++ uint evq, /* evq id */
++ uint enable, /* 1 to enable, 0 to disable */
++ uint buf_base_id,/* Buffer table base for EVQ */
++ uint evq_size /* Number of events */ )
++{
++ FALCON_LOCK_DECL;
++ uint i, val;
++ ulong offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ /* size must be one of the various options, otherwise we assert */
++ for (i = 0; i < N_EVENTQ_SIZES; i++) {
++ if (evq_size <= eventq_sizes[i])
++ break;
++ }
++ EFHW_ASSERT(i < N_EVENTQ_SIZES);
++
++ __DWCHCK(EVQ_BUF_BASE_ID_LBN, EVQ_BUF_BASE_ID_WIDTH);
++ __DWCHCK(EVQ_SIZE_LBN, EVQ_SIZE_WIDTH);
++ __DWCHCK(EVQ_EN_LBN, EVQ_EN_WIDTH);
++
++ __RANGECHCK(i, EVQ_SIZE_WIDTH);
++ __RANGECHCK(buf_base_id, EVQ_BUF_BASE_ID_WIDTH);
++ __RANGECHCK(1, EVQ_EN_WIDTH);
++
++ /* if !enable then only evq needs to be correct, although valid
++ * values need to be passed in for other arguments to prevent
++ * assertions */
++
++ val = ((i << EVQ_SIZE_LBN) | (buf_base_id << EVQ_BUF_BASE_ID_LBN) |
++ (enable ? (1 << EVQ_EN_LBN) : 0));
++
++ EFHW_ASSERT(evq < FALCON_EVQ_TBL_NUM);
++
++ offset = EVQ_PTR_TBL_CHAR_OFST;
++ offset += evq * FALCON_REGISTER128;
++
++ EFHW_TRACE("%s: evq %u en=%x:buf=%x:size=%x->%x at %lx",
++ __FUNCTION__, evq, enable, buf_base_id, evq_size, val,
++ offset);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + offset, val, FALCON_ATOMIC_PTR_TBL_REG);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++
++ /* caller must wait for an update done event before writing any more
++ table entries */
++
++ return;
++}
++
++void
++falcon_nic_evq_ack(struct efhw_nic *nic,
++ uint evq, /* evq id */
++ uint rptr, /* new read pointer update */
++ bool wakeup /* request a wakeup event if ptr's != */
++ )
++{
++ uint val;
++ ulong offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ EFHW_BUILD_ASSERT(FALCON_EVQ_CHAR == 4);
++
++ __DWCHCK(EVQ_RPTR_LBN, EVQ_RPTR_WIDTH);
++ __RANGECHCK(rptr, EVQ_RPTR_WIDTH);
++
++ val = (rptr << EVQ_RPTR_LBN);
++
++ EFHW_ASSERT(evq < FALCON_EVQ_TBL_NUM);
++
++ if (evq < FALCON_EVQ_CHAR) {
++ offset = EVQ_RPTR_REG_KER_OFST;
++ offset += evq * FALCON_REGISTER128;
++
++ EFHW_ASSERT(!wakeup); /* don't try this at home */
++ } else {
++ offset = EVQ_RPTR_REG_OFST + (FALCON_EVQ_CHAR *
++ FALCON_REGISTER128);
++ offset += (evq - FALCON_EVQ_CHAR) * FALCON_REGISTER128;
++
++ /* nothing to do for interruptless event queues which do
++ * not want a wakeup */
++ if (evq != FALCON_EVQ_CHAR && !wakeup)
++ return;
++ }
++
++ EFHW_TRACE("%s: %x %x %x->%x", __FUNCTION__, evq, rptr, wakeup, val);
++
++ writel(val, efhw_kva + offset);
++ mmiowb();
++}
++
++/*----------------------------------------------------------------------------
++ *
++ * Helper for evq mapping
++ *
++ * idx = 0 && char => hw eventq[4]
++ * idx = 0 && net => hw eventq[0]
++ * 0 < idx < 5 => hw eventq[idx] (5 is non-interrupting)
++ *
++ *
++ *---------------------------------------------------------------------------*/
++
++int falcon_idx_to_evq(struct efhw_nic *nic, uint idx)
++{
++ EFHW_BUILD_ASSERT(FALCON_EVQ_CHAR == 4);
++ EFHW_ASSERT(idx <= FALCON_EVQ_NONIRQ);
++ return (idx > 0) ? idx : FALCON_EVQ_CHAR;
++}
++
++static inline int falcon_evq_is_interrupting(struct efhw_nic *nic, uint idx)
++{
++ EFHW_BUILD_ASSERT(FALCON_EVQ_CHAR == 4);
++ EFHW_ASSERT(idx <= FALCON_EVQ_NONIRQ);
++
++ /* only the first CHAR driver event queue is interrupting */
++ return (idx == FALCON_EVQ_CHAR);
++}
++
++static inline void
++falcon_drv_ev(struct efhw_nic *nic, uint64_t data, uint qid)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ /* send an event from one driver to the other */
++ EFHW_BUILD_ASSERT(DRV_EV_REG_KER_OFST == DRV_EV_REG_OFST);
++ EFHW_BUILD_ASSERT(DRV_EV_DATA_LBN == 0);
++ EFHW_BUILD_ASSERT(DRV_EV_DATA_WIDTH == 64);
++ EFHW_BUILD_ASSERT(DRV_EV_QID_LBN == 64);
++ EFHW_BUILD_ASSERT(DRV_EV_QID_WIDTH == 12);
++
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + DRV_EV_REG_OFST, data, qid);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++_DEBUG_SYM_ void
++falcon_timer_cmd(struct efhw_nic *nic,
++ uint evq, /* timer id */
++ uint mode, /* mode bits */
++ uint countdown /* counting value to set */ )
++{
++ FALCON_LOCK_DECL;
++ uint val;
++ ulong offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ EFHW_BUILD_ASSERT(TIMER_VAL_LBN == 0);
++
++ __DWCHCK(TIMER_MODE_LBN, TIMER_MODE_WIDTH);
++ __DWCHCK(TIMER_VAL_LBN, TIMER_VAL_WIDTH);
++
++ __RANGECHCK(mode, TIMER_MODE_WIDTH);
++ __RANGECHCK(countdown, TIMER_VAL_WIDTH);
++
++ val = ((mode << TIMER_MODE_LBN) | (countdown << TIMER_VAL_LBN));
++
++ if (evq < FALCON_EVQ_CHAR) {
++ offset = TIMER_CMD_REG_KER_OFST;
++ offset += evq * EFHW_8K; /* PAGE mapped register */
++ } else {
++ offset = TIMER_TBL_OFST;
++ offset += evq * FALCON_REGISTER128;
++ }
++ EFHW_ASSERT(evq < FALCON_EVQ_TBL_NUM);
++
++ EFHW_TRACE("%s: evq %u mode %x (%s) time %x -> %08x",
++ __FUNCTION__, evq, mode,
++ mode == 0 ? "DISABLE" :
++ mode == 1 ? "IMMED" :
++ mode == 2 ? (evq < 5 ? "HOLDOFF" : "RX_TRIG") :
++ "<BAD>", countdown, val);
++
++ /* Falcon requires 128 bit atomic access for this register when
++ * accessed from the driver. User access to timers is paged mapped
++ */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + offset, val, FALCON_ATOMIC_TIMER_CMD_REG);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++ return;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Rate pacing - Low level interface
++ *
++ *--------------------------------------------------------------------*/
++void falcon_nic_pace(struct efhw_nic *nic, uint dmaq, uint pace)
++{
++ /* Pace specified in 2^(units of microseconds). This is the minimum
++ additional delay imposed over and above the IPG.
++
++ Pacing only available on the virtual interfaces
++ */
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ ulong offset;
++
++ if (pace > 20)
++ pace = 20; /* maxm supported value */
++
++ __DWCHCK(TX_PACE_LBN, TX_PACE_WIDTH);
++ __RANGECHCK(pace, TX_PACE_WIDTH);
++
++ switch (nic->devtype.variant) {
++ case 'A':
++ EFHW_ASSERT(dmaq >= TX_PACE_TBL_FIRST_QUEUE_A1);
++ offset = TX_PACE_TBL_A1_OFST;
++ offset += (dmaq - TX_PACE_TBL_FIRST_QUEUE_A1) * 16;
++ break;
++ case 'B':
++ /* Would be nice to assert this, but as dmaq is unsigned and
++ * TX_PACE_TBL_FIRST_QUEUE_B0 is 0, it makes no sense
++ * EFHW_ASSERT(dmaq >= TX_PACE_TBL_FIRST_QUEUE_B0);
++ */
++ offset = TX_PACE_TBL_B0_OFST;
++ offset += (dmaq - TX_PACE_TBL_FIRST_QUEUE_B0) * 16;
++ break;
++ default:
++ EFHW_ASSERT(0);
++ offset = 0;
++ break;
++ }
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + offset, pace, FALCON_ATOMIC_PACE_REG);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++
++ EFHW_TRACE("%s: txq %d offset=%lx pace=2^%x",
++ __FUNCTION__, dmaq, offset, pace);
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Interrupt - Low level interface
++ *
++ *--------------------------------------------------------------------*/
++
++static void falcon_nic_handle_fatal_int(struct efhw_nic *nic)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ uint64_t val;
++
++ offset = (efhw_kva + FATAL_INTR_REG_OFST);
++
++ /* Falcon requires 32 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ val = readl(offset);
++ FALCON_LOCK_UNLOCK(nic);
++
++ /* ?? BUG3249 - need to disable illegal address interrupt */
++ /* ?? BUG3114 - need to backport interrupt storm protection code */
++ EFHW_ERR("fatal interrupt: %s%s%s%s%s%s%s%s%s%s%s%s[%" PRIx64 "]",
++ val & (1 << PCI_BUSERR_INT_CHAR_LBN) ? "PCI-bus-error " : "",
++ val & (1 << SRAM_OOB_INT_CHAR_LBN) ? "SRAM-oob " : "",
++ val & (1 << BUFID_OOB_INT_CHAR_LBN) ? "bufid-oob " : "",
++ val & (1 << MEM_PERR_INT_CHAR_LBN) ? "int-parity " : "",
++ val & (1 << RBUF_OWN_INT_CHAR_LBN) ? "rx-bufid-own " : "",
++ val & (1 << TBUF_OWN_INT_CHAR_LBN) ? "tx-bufid-own " : "",
++ val & (1 << RDESCQ_OWN_INT_CHAR_LBN) ? "rx-desc-own " : "",
++ val & (1 << TDESCQ_OWN_INT_CHAR_LBN) ? "tx-desc-own " : "",
++ val & (1 << EVQ_OWN_INT_CHAR_LBN) ? "evq-own " : "",
++ val & (1 << EVFF_OFLO_INT_CHAR_LBN) ? "evq-fifo " : "",
++ val & (1 << ILL_ADR_INT_CHAR_LBN) ? "ill-addr " : "",
++ val & (1 << SRM_PERR_INT_CHAR_LBN) ? "sram-parity " : "", val);
++}
++
++static void falcon_nic_interrupt_hw_enable(struct efhw_nic *nic)
++{
++ FALCON_LOCK_DECL;
++ uint val;
++ efhw_ioaddr_t offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ EFHW_BUILD_ASSERT(DRV_INT_EN_CHAR_WIDTH == 1);
++
++ if (nic->flags & NIC_FLAG_NO_INTERRUPT)
++ return;
++
++ offset = (efhw_kva + INT_EN_REG_CHAR_OFST);
++ val = 1 << DRV_INT_EN_CHAR_LBN;
++
++ EFHW_NOTICE("%s: %x -> %x", __FUNCTION__, (int)(offset - efhw_kva),
++ val);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(offset, val, FALCON_ATOMIC_INT_EN_REG);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++static void falcon_nic_interrupt_hw_disable(struct efhw_nic *nic)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ EFHW_BUILD_ASSERT(SRAM_PERR_INT_KER_WIDTH == 1);
++ EFHW_BUILD_ASSERT(DRV_INT_EN_KER_LBN == 0);
++ EFHW_BUILD_ASSERT(SRAM_PERR_INT_CHAR_WIDTH == 1);
++ EFHW_BUILD_ASSERT(DRV_INT_EN_CHAR_LBN == 0);
++ EFHW_BUILD_ASSERT(SRAM_PERR_INT_KER_LBN == SRAM_PERR_INT_CHAR_LBN);
++ EFHW_BUILD_ASSERT(DRV_INT_EN_KER_LBN == DRV_INT_EN_CHAR_LBN);
++
++ if (nic->flags & NIC_FLAG_NO_INTERRUPT)
++ return;
++
++ offset = (efhw_kva + INT_EN_REG_CHAR_OFST);
++
++ EFHW_NOTICE("%s: %x -> 0", __FUNCTION__, (int)(offset - efhw_kva));
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(offset, 0, FALCON_ATOMIC_INT_EN_REG);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++#ifndef __ci_ul_driver__
++
++static void falcon_nic_irq_addr_set(struct efhw_nic *nic, dma_addr_t dma_addr)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t offset;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++
++ offset = (efhw_kva + INT_ADR_REG_CHAR_OFST);
++
++ EFHW_NOTICE("%s: %x -> " DMA_ADDR_T_FMT, __FUNCTION__,
++ (int)(offset - efhw_kva), dma_addr);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(offset, dma_addr, FALCON_ATOMIC_INT_ADR_REG);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++#endif
++
++
++/*--------------------------------------------------------------------
++ *
++ * RXDP - low level interface
++ *
++ *--------------------------------------------------------------------*/
++
++void
++falcon_nic_set_rx_usr_buf_size(struct efhw_nic *nic, int usr_buf_bytes)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ uint64_t val, val2, usr_buf_size = usr_buf_bytes / 32;
++ int rubs_lbn, rubs_width, roec_lbn;
++
++ EFHW_BUILD_ASSERT(RX_CFG_REG_OFST == RX_CFG_REG_KER_OFST);
++
++ switch (nic->devtype.variant) {
++ default:
++ EFHW_ASSERT(0);
++ /* Fall-through to avoid compiler warnings. */
++ case 'A':
++ rubs_lbn = RX_USR_BUF_SIZE_A1_LBN;
++ rubs_width = RX_USR_BUF_SIZE_A1_WIDTH;
++ roec_lbn = RX_OWNERR_CTL_A1_LBN;
++ break;
++ case 'B':
++ rubs_lbn = RX_USR_BUF_SIZE_B0_LBN;
++ rubs_width = RX_USR_BUF_SIZE_B0_WIDTH;
++ roec_lbn = RX_OWNERR_CTL_B0_LBN;
++ break;
++ }
++
++ __DWCHCK(rubs_lbn, rubs_width);
++ __QWCHCK(roec_lbn, 1);
++ __RANGECHCK(usr_buf_size, rubs_width);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_read_qq(efhw_kva + RX_CFG_REG_OFST, &val, &val2);
++
++ val &= ~((__FALCON_MASK64(rubs_width)) << rubs_lbn);
++ val |= (usr_buf_size << rubs_lbn);
++
++ /* shouldn't be needed for a production driver */
++ val |= ((uint64_t) 1 << roec_lbn);
++
++ falcon_write_qq(efhw_kva + RX_CFG_REG_OFST, val, val2);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++EXPORT_SYMBOL(falcon_nic_set_rx_usr_buf_size);
++
++void
++falcon_nic_rx_filter_ctl_get(struct efhw_nic *nic, uint32_t *tcp_full,
++ uint32_t *tcp_wild,
++ uint32_t *udp_full, uint32_t *udp_wild)
++{
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ FALCON_LOCK_DECL;
++ uint64_t val;
++
++ FALCON_LOCK_LOCK(nic);
++ falcon_read_q(efhw_kva + RX_FILTER_CTL_REG_OFST, &val);
++ FALCON_LOCK_UNLOCK(nic);
++
++ *tcp_full = (uint32_t)((val >> TCP_FULL_SRCH_LIMIT_LBN) &
++ (__FALCON_MASK64(TCP_FULL_SRCH_LIMIT_WIDTH)));
++
++ *tcp_wild = (uint32_t)((val >> TCP_WILD_SRCH_LIMIT_LBN) &
++ (__FALCON_MASK64(TCP_WILD_SRCH_LIMIT_WIDTH)));
++
++ *udp_full = (uint32_t)((val >> UDP_FULL_SRCH_LIMIT_LBN) &
++ (__FALCON_MASK64(UDP_FULL_SRCH_LIMIT_WIDTH)));
++
++ *udp_wild = (uint32_t)((val >> UDP_WILD_SRCH_LIMIT_LBN) &
++ (__FALCON_MASK64(UDP_WILD_SRCH_LIMIT_WIDTH)));
++}
++EXPORT_SYMBOL(falcon_nic_rx_filter_ctl_get);
++
++void
++falcon_nic_rx_filter_ctl_set(struct efhw_nic *nic, uint32_t tcp_full,
++ uint32_t tcp_wild,
++ uint32_t udp_full, uint32_t udp_wild)
++{
++ uint64_t val, val2;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ FALCON_LOCK_DECL;
++
++ EFHW_ASSERT(tcp_full < nic->filter_tbl_size);
++ EFHW_ASSERT(tcp_wild < nic->filter_tbl_size);
++ EFHW_ASSERT(udp_full < nic->filter_tbl_size);
++ EFHW_ASSERT(udp_wild < nic->filter_tbl_size);
++
++ /* until we implement a dynamic scaling of search limits we wish to
++ * maintain the same limits set up by default in the net driver
++ * when we initialize the char driver */
++ tcp_full_srch_limit = tcp_full;
++ tcp_wild_srch_limit = tcp_wild;
++ udp_full_srch_limit = udp_full;
++ udp_wild_srch_limit = udp_wild;
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &val, &val2);
++
++ /* Search limits */
++ val &= ~((__FALCON_MASK64(TCP_FULL_SRCH_LIMIT_WIDTH))
++ << TCP_FULL_SRCH_LIMIT_LBN);
++
++ val |= ((uint64_t)tcp_full + RX_FILTER_CTL_SRCH_FUDGE_FULL)
++ << TCP_FULL_SRCH_LIMIT_LBN;
++
++ val &= ~((__FALCON_MASK64(TCP_WILD_SRCH_LIMIT_WIDTH))
++ << TCP_WILD_SRCH_LIMIT_LBN);
++
++ val |= ((uint64_t)tcp_wild + RX_FILTER_CTL_SRCH_FUDGE_WILD)
++ << TCP_WILD_SRCH_LIMIT_LBN;
++
++ val &= ~((__FALCON_MASK64(UDP_FULL_SRCH_LIMIT_WIDTH))
++ << UDP_FULL_SRCH_LIMIT_LBN);
++
++ val |= ((uint64_t)udp_full + RX_FILTER_CTL_SRCH_FUDGE_FULL)
++ << UDP_FULL_SRCH_LIMIT_LBN;
++
++ val &= ~((__FALCON_MASK64(UDP_WILD_SRCH_LIMIT_WIDTH))
++ << UDP_WILD_SRCH_LIMIT_LBN);
++
++ val |= ((uint64_t)udp_wild + RX_FILTER_CTL_SRCH_FUDGE_WILD)
++ << UDP_WILD_SRCH_LIMIT_LBN;
++
++ falcon_write_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, val, val2);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++EXPORT_SYMBOL(falcon_nic_rx_filter_ctl_set);
++
++/*--------------------------------------------------------------------
++ *
++ * TXDP - low level interface
++ *
++ *--------------------------------------------------------------------*/
++
++_DEBUG_SYM_ void falcon_nic_tx_cfg(struct efhw_nic *nic, int unlocked)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ uint64_t val1, val2;
++
++ EFHW_BUILD_ASSERT(TX_CFG_REG_OFST == TX_CFG_REG_KER_OFST);
++ __DWCHCK(TX_OWNERR_CTL_LBN, TX_OWNERR_CTL_WIDTH);
++ __DWCHCK(TX_NON_IP_DROP_DIS_LBN, TX_NON_IP_DROP_DIS_WIDTH);
++
++ FALCON_LOCK_LOCK(nic);
++ falcon_read_qq(efhw_kva + TX_CFG_REG_OFST, &val1, &val2);
++
++ /* Will flag fatal interrupts on owner id errors. This should not be
++ on for production code because there is otherwise a denial of
++ serivce attack possible */
++ val1 |= (1 << TX_OWNERR_CTL_LBN);
++
++ /* Setup user queue TCP/UDP only packet security */
++ if (unlocked)
++ val1 |= (1 << TX_NON_IP_DROP_DIS_LBN);
++ else
++ val1 &= ~(1 << TX_NON_IP_DROP_DIS_LBN);
++
++ falcon_write_qq(efhw_kva + TX_CFG_REG_OFST, val1, val2);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Random thresholds - Low level interface (Would like these to be op
++ * defaults wherever possible)
++ *
++ *--------------------------------------------------------------------*/
++
++static void falcon_nic_pace_cfg(struct efhw_nic *nic)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ unsigned offset = 0;
++ uint64_t val;
++
++ val = 0xa81682; /* !!!! */
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ switch (nic->devtype.variant) {
++ case 'A': offset = TX_PACE_REG_A1_OFST; break;
++ case 'B': offset = TX_PACE_REG_B0_OFST; break;
++ default: EFHW_ASSERT(0); break;
++ }
++ falcon_write_qq(efhw_kva + offset, val, 0);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++/**********************************************************************
++ * Supporting modules. ************************************************
++ **********************************************************************/
++
++/*--------------------------------------------------------------------
++ *
++ * Filter support
++ *
++ *--------------------------------------------------------------------*/
++
++/*! \TODO this table should be per nic */
++struct falcon_cached_ipfilter {
++#if FALCON_FULL_FILTER_CACHE
++ unsigned dmaq;
++ unsigned saddr_le32;
++ unsigned daddr_le32;
++ unsigned sport_le16;
++ unsigned dport_le16;
++ unsigned tcp:1;
++ unsigned full:1;
++ unsigned rss_b0:1;
++ unsigned scat_b0:1;
++#endif
++ unsigned addr_valid:1;
++
++};
++
++
++/* TODO: Dynamically allocate this and store in struct efhw_nic. */
++static struct falcon_cached_ipfilter
++ host_ipfilter_cache[EFHW_MAX_NR_DEVS][FALCON_FILTER_TBL_NUM];
++
++
++static inline void host_ipfilter_cache_init(struct efhw_nic *nic)
++{
++ memset(host_ipfilter_cache[nic->index], 0,
++ sizeof(host_ipfilter_cache[0][0]) * nic->filter_tbl_size);
++}
++
++static inline int host_ipfilter_cache_active(struct efhw_nic *nic, uint idx)
++{
++ EFHW_ASSERT(nic->index < EFHW_MAX_NR_DEVS);
++ EFHW_ASSERT(idx < nic->filter_tbl_size);
++
++ return (host_ipfilter_cache[nic->index][idx].addr_valid);
++
++}
++
++static inline void host_ipfilter_cache_flush(struct efhw_nic *nic, uint idx)
++{
++ EFHW_ASSERT(nic->index < EFHW_MAX_NR_DEVS);
++ EFHW_ASSERT(idx < nic->filter_tbl_size);
++
++ memset(&host_ipfilter_cache[nic->index][idx], 0,
++ sizeof(struct falcon_cached_ipfilter));
++ mmiowb();
++}
++
++static inline void
++host_ipfilter_cache_set_addr(struct efhw_nic *nic, uint idx, uint dmaq,
++ unsigned tcp, unsigned full,
++ unsigned rss_b0, unsigned scat_b0,
++ unsigned saddr_le32, unsigned sport_le16,
++ unsigned daddr_le32, unsigned dport_le16)
++{
++ unsigned nic_i = nic->index;
++
++ EFHW_ASSERT(nic_i < EFHW_MAX_NR_DEVS);
++ EFHW_ASSERT(idx < nic->filter_tbl_size);
++ EFHW_ASSERT(!host_ipfilter_cache[nic_i][idx].addr_valid);
++
++ __RANGECHCK(sport_le16, SRC_TCP_DEST_UDP_1_WIDTH);
++ __RANGECHCK(dport_le16, SRC_TCP_DEST_UDP_1_WIDTH);
++
++#if FALCON_FULL_FILTER_CACHE
++ host_ipfilter_cache[nic_i][idx].dmaq = dmaq;
++ host_ipfilter_cache[nic_i][idx].saddr_le32 = saddr_le32;
++ host_ipfilter_cache[nic_i][idx].daddr_le32 = daddr_le32;
++ host_ipfilter_cache[nic_i][idx].sport_le16 = sport_le16;
++ host_ipfilter_cache[nic_i][idx].dport_le16 = dport_le16;
++ host_ipfilter_cache[nic_i][idx].tcp = tcp;
++ host_ipfilter_cache[nic_i][idx].full = full;
++ host_ipfilter_cache[nic_i][idx].rss_b0 = rss_b0;
++ host_ipfilter_cache[nic_i][idx].scat_b0 = scat_b0;
++#endif
++ host_ipfilter_cache[nic_i][idx].addr_valid = 1;
++ mmiowb();
++}
++
++#if FALCON_VERIFY_FILTERS
++/* Check that all active filters still exist by reading from H/W */
++static void _falcon_nic_ipfilter_sanity(struct efhw_nic *nic)
++{
++ unsigned i;
++ struct falcon_cached_ipfilter *f;
++ uint64_t q0_expect, q1_expect, q0_got, q1_got;
++
++ for (i = 0; i < nic->filter_tbl_size; i++) {
++ f = host_ipfilter_cache[nic->index] + i;
++ if (!f->addr_valid)
++ continue;
++
++ _falcon_nic_ipfilter_build(nic, f->tcp, f->full,
++ f->rss_b0, f->scat_b0, i, f->dmaq,
++ f->saddr_le32, f->sport_le16,
++ f->daddr_le32, f->dport_le16,
++ &q0_expect, &q1_expect);
++
++ falcon_read_qq(EFHW_KVA(nic) + RX_FILTER_TBL0_OFST +
++ i * 2 * FALCON_REGISTER128,
++ &q0_got, &q1_got);
++
++ if ((q0_got != q0_expect) || (q1_got != q1_expect)) {
++ falcon_write_qq(EFHW_KVA(nic) + 0x300,
++ q0_got, q1_got);
++ EFHW_ERR("ERROR: RX-filter[%d][%d] was "
++ "%"PRIx64":%" PRIx64" expected "
++ "%"PRIx64":%"PRIx64,
++ nic->index, i, q0_got, q1_got,
++ q0_expect, q1_expect);
++ }
++ }
++}
++#endif /* FALCON_VERIFY_FILTERS */
++
++#if FALCON_FULL_FILTER_CACHE
++static inline int
++host_ipfilter_cache_check_not(uint nic, uint idx, int tcp, int full,
++ unsigned saddr_le32, unsigned sport_le16,
++ unsigned daddr_le32, unsigned dport_le16)
++{
++ return ((host_ipfilter_cache[nic][idx].saddr_le32 != saddr_le32) ||
++ (host_ipfilter_cache[nic][idx].daddr_le32 != daddr_le32) ||
++ (host_ipfilter_cache[nic][idx].sport_le16 != sport_le16) ||
++ (host_ipfilter_cache[nic][idx].dport_le16 != dport_le16) ||
++ (host_ipfilter_cache[nic][idx].tcp != tcp) ||
++ (host_ipfilter_cache[nic][idx].full != full));
++}
++#endif
++
++#define host_ipfilter_cache_saddr_le32(nic, idx) \
++ host_ipfilter_cache[nic][idx].saddr_le32
++#define host_ipfilter_cache_daddr_le32(nic, idx) \
++ host_ipfilter_cache[nic][idx].daddr_le32
++#define host_ipfilter_cache_sport_le16(nic, idx) \
++ host_ipfilter_cache[nic][idx].sport_le16
++#define host_ipfilter_cache_dport_le16(nic, idx) \
++ host_ipfilter_cache[nic][idx].dport_le16
++#define host_ipfilter_cache_tcp(nic, idx) \
++ host_ipfilter_cache[nic][idx].tcp
++#define host_ipfilter_cache_full(nic, idx) \
++ host_ipfilter_cache[nic][idx].full
++
++/**********************************************************************
++ * Implementation of the HAL. ********************************************
++ **********************************************************************/
++
++/*----------------------------------------------------------------------------
++ *
++ * Initialisation and configuration discovery
++ *
++ *---------------------------------------------------------------------------*/
++
++#ifdef __ci_ul_driver__
++
++static int falcon_nic_init_irq_channel(struct efhw_nic *nic, int enable)
++{
++ EFHW_ERR("%s: not implemented for ul driver", __FUNCTION__);
++ return -EOPNOTSUPP;
++}
++
++#else
++
++static int falcon_nic_init_irq_channel(struct efhw_nic *nic, int enable)
++{
++ /* create a buffer for the irq channel */
++ int rc;
++
++ if (enable) {
++ rc = efhw_iopage_alloc(nic, &nic->irq_iobuff);
++ if (rc < 0)
++ return rc;
++
++ falcon_nic_irq_addr_set(nic,
++ efhw_iopage_dma_addr(&nic->irq_iobuff));
++ } else {
++ if (efhw_iopage_is_valid(&nic->irq_iobuff))
++ efhw_iopage_free(nic, &nic->irq_iobuff);
++
++ efhw_iopage_mark_invalid(&nic->irq_iobuff);
++ falcon_nic_irq_addr_set(nic, 0);
++ }
++
++ EFHW_TRACE("%s: " ci_dma_addr_fmt " %sable", __FUNCTION__,
++ efhw_iopage_dma_addr(&nic->irq_iobuff), enable ?
++ "en" : "dis");
++
++ return 0;
++}
++
++#endif
++
++static void falcon_nic_close_hardware(struct efhw_nic *nic)
++{
++ /* check we are in possession of some hardware */
++ if (!efhw_nic_have_hw(nic))
++ return;
++
++ falcon_nic_init_irq_channel(nic, 0);
++
++ EFHW_NOTICE("%s:", __FUNCTION__);
++}
++
++#ifdef __ci_ul_driver__
++extern
++#else
++static
++#endif
++int falcon_nic_get_mac_config(struct efhw_nic *nic)
++{
++ efhw_ioaddr_t efhw_kva = nic->bar_ioaddr;
++ int is_mac_type_1g;
++ uint32_t strap, altera;
++ uint64_t rx_cfg, r;
++
++ altera = readl(efhw_kva + ALTERA_BUILD_REG_OFST);
++ strap = readl(efhw_kva + STRAP_REG_KER_OFST) & 0x7;
++
++ switch (nic->devtype.variant) {
++ case 'A':
++ if ((altera & 0x0fff0000) == 0x1130000) {
++ strap = 2; /* FPGA - PCI-X 2G */
++ } else if ((altera & 0x00ff0000) == 0x140000) {
++ /* should be 114 */
++ strap = 4; /* FPGA - PCI-X 4G */
++ } else if (strap < 2 || strap > 5) {
++ EFHW_ERR("Invalid strap option %d altera_buid_ver=%x",
++ strap, altera);
++ return -EINVAL;
++ }
++ is_mac_type_1g = (0 != (strap & 2));
++ break;
++ case 'B':
++ /* Runtime check that the hardware and software agree about
++ * the size of the RXFIFO. Write binary 11 across the left
++ * most bit, and assert we get 1 back.
++ */
++ r = 1LL << RX_TOEP_TCP_SUPPRESS_B0_LBN;
++ r |= (r << 1);
++
++ /* Save the original value */
++ falcon_read_q(efhw_kva + RX_CFG_REG_OFST, &rx_cfg);
++
++ /* Write and ready the dummy value */
++ falcon_write_qq(efhw_kva + RX_CFG_REG_OFST, r, 0);
++ falcon_read_q(efhw_kva + RX_CFG_REG_OFST, &r);
++
++ /* Restore the original value */
++ falcon_write_qq(efhw_kva + RX_CFG_REG_OFST, rx_cfg, 0);
++
++ if (r != (1LL << RX_TOEP_TCP_SUPPRESS_B0_LBN)) {
++ EFHW_ERR("The FPGA build (%x) RXFIFO size does not "
++ "match the software", altera);
++ return -EINVAL;
++ }
++ is_mac_type_1g = (0 != (strap & 2));
++#if FALCON_MAC_SET_TYPE_BY_SPEED
++ /* Check the selected strap pins against the MAC speed -
++ * and adjust if necessary.
++ */
++ {
++ int speed;
++ speed = readl(efhw_kva + MAC0_CTRL_REG_OFST) & 0x3;
++ is_mac_type_1g = (speed <= 2);
++ }
++#endif
++ break;
++ default:
++ EFHW_ASSERT(0);
++ is_mac_type_1g = 0;
++ break;
++ }
++
++ nic->fpga_version = altera;
++
++ /* We can now set the MAC type correctly based on the strap pins. */
++ if (is_mac_type_1g) {
++ nic->flags &= ~NIC_FLAG_10G;
++ } else {
++ /* strap & 4 must be set according to checks above */
++ nic->flags |= NIC_FLAG_10G;
++ }
++ EFHW_NOTICE("Board has %s MAC: strap=%d",
++ 0 != (nic->flags & NIC_FLAG_10G) ? "10G" : "1G", strap);
++ return 0;
++}
++
++static int
++falcon_nic_init_hardware(struct efhw_nic *nic,
++ struct efhw_ev_handler *ev_handlers,
++ const uint8_t *mac_addr)
++{
++ int rc;
++
++ /* header sanity checks */
++ FALCON_ASSERT_VALID();
++
++ rc = falcon_nic_get_mac_config(nic);
++ if (rc < 0)
++ return rc;
++
++ /* Initialise supporting modules */
++ falcon_nic_ipfilter_ctor(nic);
++
++#if FALCON_USE_SHADOW_BUFFER_TABLE
++ CI_ZERO_ARRAY(_falcon_buffer_table, FALCON_BUFFER_TBL_NUM);
++#endif
++
++ /* Initialise the top level hardware blocks */
++ memcpy(nic->mac_addr, mac_addr, ETH_ALEN);
++
++ EFHW_TRACE("%s:", __FUNCTION__);
++
++ /* nic.c:efhw_nic_init marks all the interrupt units as unused.
++
++ ?? TODO we should be able to request the non-interrupting event
++ queue and the net driver's (for a net driver that is using libefhw)
++ additional RSS queues here.
++
++ Result would be that that net driver could call
++ nic.c:efhw_nic_allocate_common_hardware_resources() and that the
++ IFDEF FALCON's can be removed from
++ nic.c:efhw_nic_allocate_common_hardware_resources()
++ */
++ nic->irq_unit[0] = INT_EN_REG_CHAR_OFST;
++
++ /*****************************************************************
++ * The rest of this function deals with initialization of the NICs
++ * hardware (as opposed to the initialization of the
++ * struct efhw_nic data structure */
++
++ /* char driver grabs SRM events onto the non interrupting
++ * event queue */
++ falcon_nic_srm_upd_evq(nic, FALCON_EVQ_NONIRQ);
++
++ /* RXDP tweaks */
++
++ /* ?? bug2396 rx_cfg should be ok so long as the net driver
++ * always pushes buffers big enough for the link MTU */
++
++ /* set the RX buffer cutoff size to be the same as PAGE_SIZE.
++ * Use this value when we think that there will be a lot of
++ * jumbo frames.
++ *
++ * The default value 1600 is useful when packets are small,
++ * but would means that jumbo frame RX queues would need more
++ * descriptors pushing */
++ falcon_nic_set_rx_usr_buf_size(nic, FALCON_RX_USR_BUF_SIZE);
++
++ /* TXDP tweaks */
++ /* ?? bug2396 looks ok */
++ falcon_nic_tx_cfg(nic, /*unlocked(for non-UDP/TCP)= */ 0);
++ falcon_nic_pace_cfg(nic);
++
++ /* ?? bug2396
++ * netdriver must load first or else must RMW this register */
++ falcon_nic_rx_filter_ctl_set(nic, RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL,
++ RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD,
++ RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL,
++ RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD);
++
++ if (!(nic->flags & NIC_FLAG_NO_INTERRUPT)) {
++ rc = efhw_keventq_ctor(nic, FALCON_EVQ_CHAR, &nic->evq[0],
++ ev_handlers);
++ if (rc < 0) {
++ EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d",
++ __FUNCTION__, rc, FALCON_EVQ_CHAR);
++ return rc;
++ }
++ }
++ rc = efhw_keventq_ctor(nic, FALCON_EVQ_NONIRQ,
++ &nic->evq[FALCON_EVQ_NONIRQ], NULL);
++ if (rc < 0) {
++ EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d",
++ __FUNCTION__, rc, FALCON_EVQ_NONIRQ);
++ return rc;
++ }
++
++ /* allocate IRQ channel */
++ rc = falcon_nic_init_irq_channel(nic, 1);
++ /* ignore failure at user-level for eftest */
++ if ((rc < 0) && !(nic->options & NIC_OPT_EFTEST))
++ return rc;
++
++ return 0;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Interrupt
++ *
++ *--------------------------------------------------------------------*/
++
++static void
++falcon_nic_interrupt_enable(struct efhw_nic *nic, unsigned idx)
++{
++ int evq;
++
++ if (idx || (nic->flags & NIC_FLAG_NO_INTERRUPT))
++ return;
++
++ /* Enable driver interrupts */
++ EFHW_NOTICE("%s: enable master interrupt", __FUNCTION__);
++ falcon_nic_interrupt_hw_enable(nic);
++
++ /* An interrupting eventq must start of day ack its read pointer */
++ evq = falcon_idx_to_evq(nic, idx);
++
++ if (falcon_evq_is_interrupting(nic, evq)) {
++ struct efhw_keventq *q = &nic->evq[idx];
++ unsigned rdptr =
++ EFHW_EVENT_OFFSET(q, q, 1) / sizeof(efhw_event_t);
++ falcon_nic_evq_ack(nic, evq, rdptr, false);
++ EFHW_NOTICE("%s: ACK evq[%d]:%x", __FUNCTION__, evq, rdptr);
++ }
++}
++
++static void falcon_nic_interrupt_disable(struct efhw_nic *nic, uint idx)
++{
++ /* NB. No need to check for NIC_FLAG_NO_INTERRUPT, as
++ ** falcon_nic_interrupt_hw_disable() will do it. */
++ if (idx)
++ return;
++ falcon_nic_interrupt_hw_disable(nic);
++}
++
++static void
++falcon_nic_set_interrupt_moderation(struct efhw_nic *nic, uint idx,
++ uint32_t val)
++{
++ falcon_timer_cmd(nic, falcon_idx_to_evq(nic, idx),
++ TIMER_MODE_INT_HLDOFF, val / 5);
++}
++
++static inline void legacy_irq_ack(struct efhw_nic *nic)
++{
++ EFHW_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT));
++
++ if (!(nic->flags & NIC_FLAG_MSI)) {
++ writel(1, EFHW_KVA(nic) + INT_ACK_REG_CHAR_A1_OFST);
++ mmiowb();
++ /* ?? FIXME: We should be doing a read here to ensure IRQ is
++ * thoroughly acked before we return from ISR. */
++ }
++}
++
++static int falcon_nic_interrupt(struct efhw_nic *nic)
++{
++ volatile uint32_t *syserr_ptr =
++ (uint32_t *) efhw_iopage_ptr(&nic->irq_iobuff);
++ int handled = 0;
++ int done_ack = 0;
++
++ EFHW_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT));
++ EFHW_ASSERT(syserr_ptr);
++
++ /* FIFO fill level interrupt - just log it. */
++ if (unlikely(*(syserr_ptr + (DW0_OFST / 4)))) {
++ EFHW_WARN("%s: *** FIFO *** %x", __FUNCTION__,
++ *(syserr_ptr + (DW0_OFST / 4)));
++ *(syserr_ptr + (DW0_OFST / 4)) = 0;
++ handled++;
++ }
++
++ /* Fatal interrupts. */
++ if (unlikely(*(syserr_ptr + (DW2_OFST / 4)))) {
++ *(syserr_ptr + (DW2_OFST / 4)) = 0;
++ falcon_nic_handle_fatal_int(nic);
++ handled++;
++ }
++
++ /* Event queue interrupt. For legacy interrupts we have to check
++ * that the interrupt is for us, because it could be shared. */
++ if (*(syserr_ptr + (DW1_OFST / 4))) {
++ *(syserr_ptr + (DW1_OFST / 4)) = 0;
++ /* ACK must come before callback to handler fn. */
++ legacy_irq_ack(nic);
++ done_ack = 1;
++ handled++;
++ if (nic->irq_handler)
++ nic->irq_handler(nic, 0);
++ }
++
++ if (unlikely(!done_ack)) {
++ if (!handled)
++ /* Shared interrupt line (hopefully). */
++ return 0;
++ legacy_irq_ack(nic);
++ }
++
++ EFHW_TRACE("%s: handled %d", __FUNCTION__, handled);
++ return 1;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Event Management - and SW event posting
++ *
++ *--------------------------------------------------------------------*/
++
++static void
++falcon_nic_event_queue_enable(struct efhw_nic *nic, uint evq, uint evq_size,
++ dma_addr_t q_base_addr, /* not used */
++ uint buf_base_id)
++{
++ EFHW_ASSERT(nic);
++
++ /*!\ TODO we can be more efficient if we know whether or not there
++ * is a timer attached */
++ falcon_timer_cmd(nic, evq, 0 /* disable */ , 0);
++
++ falcon_nic_evq_ptr_tbl(nic, evq, 1, buf_base_id, evq_size);
++ EFHW_TRACE("%s: enable evq %u size %u", __FUNCTION__, evq, evq_size);
++}
++
++static void
++falcon_nic_event_queue_disable(struct efhw_nic *nic, uint evq, int timer_only)
++{
++ EFHW_ASSERT(nic);
++
++ /*!\ TODO we can be more efficient if we know whether or not there
++ * is a timer attached */
++ falcon_timer_cmd(nic, evq, 0 /* disable */ , 0);
++
++ if (!timer_only)
++ falcon_nic_evq_ptr_tbl(nic, evq, 0, 0, 0);
++ EFHW_TRACE("%s: disenable evq %u", __FUNCTION__, evq);
++}
++
++static void
++falcon_nic_wakeup_request(struct efhw_nic *nic, dma_addr_t q_base_addr,
++ int next_i, int evq)
++{
++ EFHW_ASSERT(evq > FALCON_EVQ_CHAR);
++ falcon_nic_evq_ack(nic, evq, next_i, true);
++ EFHW_TRACE("%s: evq %d next_i %d", __FUNCTION__, evq, next_i);
++}
++
++static void falcon_nic_sw_event(struct efhw_nic *nic, int data, int evq)
++{
++ uint64_t ev_data = data;
++
++ ev_data &= ~FALCON_EVENT_CODE_MASK;
++ ev_data |= FALCON_EVENT_CODE_SW;
++
++ falcon_drv_ev(nic, ev_data, evq);
++ EFHW_NOTICE("%s: evq[%d]->%x", __FUNCTION__, evq, data);
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Filter support - TODO vary the depth of the search
++ *
++ *--------------------------------------------------------------------*/
++
++void
++falcon_nic_ipfilter_ctor(struct efhw_nic *nic)
++{
++ if (nic->devtype.variant == 'B' && nic->fpga_version)
++ nic->filter_tbl_size = 8 * 1024;
++ else
++ nic->filter_tbl_size = 16 * 1024;
++
++ host_ipfilter_cache_init(nic);
++}
++
++
++static int
++falcon_nic_ipfilter_set(struct efhw_nic *nic, int type, int *_filter_idx,
++ int dmaq,
++ unsigned saddr_be32, unsigned sport_be16,
++ unsigned daddr_be32, unsigned dport_be16)
++{
++ FALCON_LOCK_DECL;
++ int tcp;
++ int full;
++ int rss_b0;
++ int scat_b0;
++ int key, hash1, hash2, idx = -1;
++ int k;
++ int rc = 0;
++ unsigned max_srch = -1;
++
++ /* oh joy of joys .. maybe one day we'll optimise */
++ unsigned int saddr = ntohl(saddr_be32);
++ unsigned int daddr = ntohl(daddr_be32);
++ unsigned int sport = ntohs(sport_be16);
++ unsigned int dport = ntohs(dport_be16);
++
++ __RANGECHCK(sport, SRC_TCP_DEST_UDP_1_WIDTH);
++ __RANGECHCK(dport, SRC_TCP_DEST_UDP_1_WIDTH);
++
++ tcp = ((type & EFHW_IP_FILTER_TYPE_TCP_MASK) != 0) ? 1 : 0;
++ full = ((type & EFHW_IP_FILTER_TYPE_FULL_MASK) != 0) ? 1 : 0;
++ rss_b0 = ((type & EFHW_IP_FILTER_TYPE_RSS_B0_MASK) != 0) ? 1 : 0;
++ scat_b0 = ((type & EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK) != 0) ? 0 : 1;
++ if (tcp && full)
++ max_srch = tcp_full_srch_limit;
++ else if (tcp && !full)
++ max_srch = tcp_wild_srch_limit;
++ else if (!tcp && full)
++ max_srch = udp_full_srch_limit;
++ else if (!tcp && !full)
++ max_srch = udp_wild_srch_limit;
++
++ EFHW_TRACE("%s: %x tcp %d full %d max_srch=%d",
++ __FUNCTION__, type, tcp, full, max_srch);
++
++ /* The second hash function is simply
++ * h2(key) = 13 LSB of (key * 2 - 1)
++ * And the index(k), or the filter table address for kth search is
++ * index(k) = 13 LSB of (h1(key) + k * h2(key))
++ */
++ key = falcon_hash_get_key(saddr, sport, daddr, dport, tcp, full);
++ hash1 = falcon_hash_function1(key, nic->filter_tbl_size);
++ hash2 = falcon_hash_function2(key, nic->filter_tbl_size);
++
++ /* Avoid race to claim a filter entry */
++ FALCON_LOCK_LOCK(nic);
++
++ for (k = 0; (unsigned)k < max_srch; k++) {
++ idx = falcon_hash_iterator(hash1, hash2, k,
++ nic->filter_tbl_size);
++
++ EFHW_TRACE("ipfilter_set[%d:%d:%d]: src=%x:%d dest=%x:%d %s",
++ *_filter_idx, idx, k,
++ saddr, sport, daddr, dport,
++ host_ipfilter_cache_active(nic, idx) ?
++ "Active" : "Clear");
++
++ if (!host_ipfilter_cache_active(nic, idx))
++ break;
++
++#if FALCON_FULL_FILTER_CACHE
++ /* Check that we are not duplicating the filter */
++ if (!host_ipfilter_cache_check_not(nic->index, idx, tcp, full,
++ saddr, sport, daddr,
++ dport)) {
++ EFHW_WARN("%s: ERROR: duplicate filter (disabling "
++ "interrupts)", __FUNCTION__);
++ FALCON_LOCK_UNLOCK(nic);
++ falcon_nic_interrupt_hw_disable(nic);
++ return -EINVAL;
++ }
++#endif
++
++ }
++ if (k == max_srch) {
++ rc = -EADDRINUSE;
++ idx = -1;
++ goto fail1;
++ }
++
++ EFHW_ASSERT(idx < (int)nic->filter_tbl_size);
++
++ host_ipfilter_cache_set_addr(nic, idx, dmaq, tcp, full, rss_b0,
++ scat_b0, saddr, sport, daddr, dport);
++
++ _falcon_nic_ipfilter_set(nic, tcp, full, rss_b0,
++ scat_b0, idx, dmaq,
++ saddr, sport, daddr, dport);
++
++ *_filter_idx = idx;
++
++ EFHW_TRACE("%s: filter %x rxq %d src " NIPQUAD_FMT
++ ":%d dest " NIPQUAD_FMT ":%d set in %d",
++ __FUNCTION__, idx, dmaq,
++ NIPQUAD(&saddr), sport, NIPQUAD(&daddr), dport, k);
++
++fail1:
++ FALCON_LOCK_UNLOCK(nic);
++ return rc;
++}
++
++static void
++falcon_nic_ipfilter_attach(struct efhw_nic *nic, int filter_idx, int dmaq_idx)
++{
++ /* Intentionally empty - Falcon attaches and sets the filter
++ * in filter_set */
++ EFHW_TRACE("%s: attach filter %x with rxq %d - ignored",
++ __FUNCTION__, filter_idx, dmaq_idx);
++}
++
++static void falcon_nic_ipfilter_detach(struct efhw_nic *nic, int filter_idx)
++{
++ /* Intentionally empty - Falcon attaches and sets the filter
++ * in filter_clear */
++ EFHW_TRACE("%s: detach filter %x from rxq - ignored",
++ __FUNCTION__, filter_idx);
++}
++
++static void falcon_nic_ipfilter_clear(struct efhw_nic *nic, int filter_idx)
++{
++ FALCON_LOCK_DECL;
++
++ EFHW_TRACE("%s: filter %x", __FUNCTION__, filter_idx);
++
++ /* In case the filter has already been freed */
++ if (filter_idx == -1)
++ return;
++
++ FALCON_LOCK_LOCK(nic);
++
++ /* if we flush a chained hash then all we need to do is zero it out */
++ host_ipfilter_cache_flush(nic, filter_idx);
++ _falcon_nic_ipfilter_clear(nic, filter_idx);
++
++ FALCON_LOCK_UNLOCK(nic);
++ return;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Buffer table - helpers
++ *
++ *--------------------------------------------------------------------*/
++
++#define FALCON_LAZY_COMMIT_HWM (FALCON_BUFFER_UPD_MAX - 16)
++
++/* Note re.:
++ * falcon_nic_buffer_table_lazy_commit(struct efhw_nic *nic)
++ * falcon_nic_buffer_table_update_poll(struct efhw_nic *nic)
++ * falcon_nic_buffer_table_confirm(struct efhw_nic *nic)
++ * -- these are no-ops in the user-level driver because it would need to
++ * coordinate with the real driver on the number of outstanding commits.
++ *
++ * An exception is made for eftest apps, which manage the hardware without
++ * using the char driver.
++ */
++
++static inline void falcon_nic_buffer_table_lazy_commit(struct efhw_nic *nic)
++{
++#if defined(__ci_ul_driver__)
++ if (!(nic->options & NIC_OPT_EFTEST))
++ return;
++#endif
++
++ /* Do nothing if operating in synchronous mode. */
++ if (!nic->irq_handler)
++ return;
++}
++
++static inline void falcon_nic_buffer_table_update_poll(struct efhw_nic *nic)
++{
++ FALCON_LOCK_DECL;
++ int count = 0, rc = 0;
++
++#if defined(__ci_ul_driver__)
++ if (!(nic->options & NIC_OPT_EFTEST))
++ return;
++#endif
++
++ /* We can be called here early days */
++ if (!nic->irq_handler)
++ return;
++
++ /* If we need to gather buffer update events then poll the
++ non-interrupting event queue */
++
++ /* For each _buffer_table_commit there will be an update done
++ event. We don't keep track of how many buffers each commit has
++ committed, just make sure that all the expected events have been
++ gathered */
++ FALCON_LOCK_LOCK(nic);
++
++ EFHW_TRACE("%s: %d", __FUNCTION__, nic->buf_commit_outstanding);
++
++ while (nic->buf_commit_outstanding > 0) {
++ /* we're not expecting to handle any events that require
++ * upcalls into the core driver */
++ struct efhw_ev_handler handler;
++ memset(&handler, 0, sizeof(handler));
++ nic->evq[FALCON_EVQ_NONIRQ].ev_handlers = &handler;
++ rc = efhw_keventq_poll(nic, &nic->evq[FALCON_EVQ_NONIRQ]);
++ nic->evq[FALCON_EVQ_NONIRQ].ev_handlers = NULL;
++
++ if (rc < 0) {
++ EFHW_ERR("%s: poll ERROR (%d:%d) ***** ",
++ __FUNCTION__, rc,
++ nic->buf_commit_outstanding);
++ goto out;
++ }
++
++ FALCON_LOCK_UNLOCK(nic);
++
++ if (count++)
++ udelay(1);
++
++ if (count > 1000) {
++ EFHW_WARN("%s: poll Timeout ***** (%d)", __FUNCTION__,
++ nic->buf_commit_outstanding);
++ nic->buf_commit_outstanding = 0;
++ return;
++ }
++ FALCON_LOCK_LOCK(nic);
++ }
++
++out:
++ FALCON_LOCK_UNLOCK(nic);
++ return;
++}
++
++void falcon_nic_buffer_table_confirm(struct efhw_nic *nic)
++{
++ /* confirm buffer table updates - should be used for items where
++ loss of data would be unacceptable. E.g for the buffers that back
++ an event or DMA queue */
++ FALCON_LOCK_DECL;
++
++#if defined(__ci_ul_driver__)
++ if (!(nic->options & NIC_OPT_EFTEST))
++ return;
++#endif
++
++ /* Do nothing if operating in synchronous mode. */
++ if (!nic->irq_handler)
++ return;
++
++ FALCON_LOCK_LOCK(nic);
++
++ _falcon_nic_buffer_table_commit(nic);
++
++ FALCON_LOCK_UNLOCK(nic);
++
++ falcon_nic_buffer_table_update_poll(nic);
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Buffer table - API
++ *
++ *--------------------------------------------------------------------*/
++
++static void
++falcon_nic_buffer_table_clear(struct efhw_nic *nic, int buffer_id, int num)
++{
++ FALCON_LOCK_DECL;
++ FALCON_LOCK_LOCK(nic);
++ _falcon_nic_buffer_table_clear(nic, buffer_id, num);
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++static void
++falcon_nic_buffer_table_set(struct efhw_nic *nic, dma_addr_t dma_addr,
++ uint bufsz, uint region,
++ int own_id, int buffer_id)
++{
++ FALCON_LOCK_DECL;
++
++ EFHW_ASSERT(region < FALCON_REGION_NUM);
++
++ EFHW_ASSERT((bufsz == EFHW_4K) ||
++ (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE));
++
++ falcon_nic_buffer_table_update_poll(nic);
++
++ FALCON_LOCK_LOCK(nic);
++
++ _falcon_nic_buffer_table_set(nic, dma_addr, bufsz, region, own_id,
++ buffer_id);
++
++ falcon_nic_buffer_table_lazy_commit(nic);
++
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++void
++falcon_nic_buffer_table_set_n(struct efhw_nic *nic, int buffer_id,
++ dma_addr_t dma_addr, uint bufsz, uint region,
++ int n_pages, int own_id)
++{
++ /* used to set up a contiguous range of buffers */
++ FALCON_LOCK_DECL;
++
++ EFHW_ASSERT(region < FALCON_REGION_NUM);
++
++ EFHW_ASSERT((bufsz == EFHW_4K) ||
++ (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE));
++
++ while (n_pages--) {
++
++ falcon_nic_buffer_table_update_poll(nic);
++
++ FALCON_LOCK_LOCK(nic);
++
++ _falcon_nic_buffer_table_set(nic, dma_addr, bufsz, region,
++ own_id, buffer_id++);
++
++ falcon_nic_buffer_table_lazy_commit(nic);
++
++ FALCON_LOCK_UNLOCK(nic);
++
++ dma_addr += bufsz;
++ }
++}
++
++/*--------------------------------------------------------------------
++ *
++ * DMA Queues - mid level API
++ *
++ *--------------------------------------------------------------------*/
++
++#if BUG5302_WORKAROUND
++
++/* Tx queues can get stuck if the software write pointer is set to an index
++ * beyond the configured size of the queue, such that they will not flush.
++ * This code can be run before attempting a flush; it will detect the bogus
++ * value and reset it. This fixes most instances of this problem, although
++ * sometimes it does not work, or we may not detect it in the first place,
++ * if the out-of-range value was replaced by an in-range value earlier.
++ * (In those cases we have to apply a bigger hammer later, if we see that
++ * the queue is still not flushing.)
++ */
++static void
++falcon_check_for_bogus_tx_dma_wptr(struct efhw_nic *nic, uint dmaq)
++{
++ FALCON_LOCK_DECL;
++ uint64_t val_low64, val_high64;
++ uint64_t size, hwptr, swptr, val;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ ulong offset = falcon_dma_tx_q_offset(nic, dmaq);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64);
++ FALCON_LOCK_UNLOCK(nic);
++
++ size = (val_low64 >> TX_DESCQ_SIZE_LBN)
++ & __FALCON_MASK64(TX_DESCQ_SIZE_WIDTH);
++ size = (1 << size) * 512;
++ hwptr = (val_high64 >> __DW3(TX_DESCQ_HW_RPTR_LBN))
++ & __FALCON_MASK64(TX_DESCQ_HW_RPTR_WIDTH);
++ swptr = (val_low64 >> TX_DESCQ_SW_WPTR_LBN)
++ & __FALCON_MASK64(__LW2(TX_DESCQ_SW_WPTR_LBN));
++ val = (val_high64)
++ &
++ __FALCON_MASK64(__DW3
++ (TX_DESCQ_SW_WPTR_LBN + TX_DESCQ_SW_WPTR_WIDTH));
++ val = val << __LW2(TX_DESCQ_SW_WPTR_LBN);
++ swptr = swptr | val;
++
++ if (swptr >= size) {
++ EFHW_WARN("Resetting bad write pointer for TXQ[%d]", dmaq);
++ writel((uint32_t) ((hwptr + 0) & (size - 1)),
++ efhw_kva + falcon_tx_dma_page_addr(dmaq) + 12);
++ mmiowb();
++ }
++}
++
++/* Here's that "bigger hammer": we reset all the pointers (hardware read,
++ * hardware descriptor cache read, software write) to zero.
++ */
++void falcon_clobber_tx_dma_ptrs(struct efhw_nic *nic, uint dmaq)
++{
++ FALCON_LOCK_DECL;
++ uint64_t val_low64, val_high64;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ ulong offset = falcon_dma_tx_q_offset(nic, dmaq);
++
++ EFHW_WARN("Recovering stuck TXQ[%d]", dmaq);
++ FALCON_LOCK_LOCK(nic);
++ falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64);
++ val_high64 &= ~(__FALCON_MASK64(TX_DESCQ_HW_RPTR_WIDTH)
++ << __DW3(TX_DESCQ_HW_RPTR_LBN));
++ val_high64 &= ~(__FALCON_MASK64(TX_DC_HW_RPTR_WIDTH)
++ << __DW3(TX_DC_HW_RPTR_LBN));
++ falcon_write_qq(efhw_kva + offset, val_low64, val_high64);
++ mmiowb();
++ writel(0, efhw_kva + falcon_tx_dma_page_addr(dmaq) + 12);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++}
++
++#endif
++
++static inline int
++__falcon_really_flush_tx_dma_channel(struct efhw_nic *nic, uint dmaq)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ uint val;
++
++ EFHW_BUILD_ASSERT(TX_FLUSH_DESCQ_REG_KER_OFST ==
++ TX_FLUSH_DESCQ_REG_OFST);
++
++ __DWCHCK(TX_FLUSH_DESCQ_CMD_LBN, TX_FLUSH_DESCQ_CMD_WIDTH);
++ __DWCHCK(TX_FLUSH_DESCQ_LBN, TX_FLUSH_DESCQ_WIDTH);
++ __RANGECHCK(dmaq, TX_FLUSH_DESCQ_WIDTH);
++
++ val = ((1 << TX_FLUSH_DESCQ_CMD_LBN) | (dmaq << TX_FLUSH_DESCQ_LBN));
++
++ EFHW_TRACE("TX DMA flush[%d]", dmaq);
++
++#if BUG5302_WORKAROUND
++ falcon_check_for_bogus_tx_dma_wptr(nic, dmaq);
++#endif
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + TX_FLUSH_DESCQ_REG_OFST,
++ val, FALCON_ATOMIC_TX_FLUSH_DESCQ);
++
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++ return 0;
++}
++
++static inline int
++__falcon_is_tx_dma_channel_flushed(struct efhw_nic *nic, uint dmaq)
++{
++ FALCON_LOCK_DECL;
++ uint64_t val_low64, val_high64;
++ uint64_t enable, flush_pending;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ ulong offset = falcon_dma_tx_q_offset(nic, dmaq);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64);
++ FALCON_LOCK_UNLOCK(nic);
++
++ /* should see one of three values for these 2 bits
++ * 1, queue enabled no flush pending
++ * - i.e. first flush request
++ * 2, queue enabled, flush pending
++ * - i.e. request to reflush before flush finished
++ * 3, queue disabled (no flush pending)
++ * - flush complete
++ */
++ __DWCHCK(TX_DESCQ_FLUSH_LBN, TX_DESCQ_FLUSH_WIDTH);
++ __DW3CHCK(TX_DESCQ_EN_LBN, TX_DESCQ_EN_WIDTH);
++ enable = val_high64 & (1 << __DW3(TX_DESCQ_EN_LBN));
++ flush_pending = val_low64 & (1 << TX_DESCQ_FLUSH_LBN);
++
++ if (enable && !flush_pending)
++ return 0;
++
++ EFHW_TRACE("%d, %s: %s, %sflush pending", dmaq, __FUNCTION__,
++ enable ? "enabled" : "disabled",
++ flush_pending ? "" : "NO ");
++ /* still in progress */
++ if (enable && flush_pending)
++ return -EALREADY;
++
++ return -EAGAIN;
++}
++
++static int falcon_flush_tx_dma_channel(struct efhw_nic *nic, uint dmaq)
++{
++ int rc;
++ rc = __falcon_is_tx_dma_channel_flushed(nic, dmaq);
++ if (rc < 0) {
++ EFHW_WARN("%s: failed %d", __FUNCTION__, rc);
++ return rc;
++ }
++ return __falcon_really_flush_tx_dma_channel(nic, dmaq);
++}
++
++static int
++__falcon_really_flush_rx_dma_channel(struct efhw_nic *nic, uint dmaq)
++{
++ FALCON_LOCK_DECL;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ uint val;
++
++ EFHW_BUILD_ASSERT(RX_FLUSH_DESCQ_REG_KER_OFST ==
++ RX_FLUSH_DESCQ_REG_OFST);
++
++ __DWCHCK(RX_FLUSH_DESCQ_CMD_LBN, RX_FLUSH_DESCQ_CMD_WIDTH);
++ __DWCHCK(RX_FLUSH_DESCQ_LBN, RX_FLUSH_DESCQ_WIDTH);
++ __RANGECHCK(dmaq, RX_FLUSH_DESCQ_WIDTH);
++
++ val = ((1 << RX_FLUSH_DESCQ_CMD_LBN) | (dmaq << RX_FLUSH_DESCQ_LBN));
++
++ EFHW_TRACE("RX DMA flush[%d]", dmaq);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_write_qq(efhw_kva + RX_FLUSH_DESCQ_REG_OFST, val,
++ FALCON_ATOMIC_RX_FLUSH_DESCQ);
++ mmiowb();
++ FALCON_LOCK_UNLOCK(nic);
++ return 0;
++}
++
++static inline int
++__falcon_is_rx_dma_channel_flushed(struct efhw_nic *nic, uint dmaq)
++{
++ FALCON_LOCK_DECL;
++ uint64_t val;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ ulong offset = falcon_dma_rx_q_offset(nic, dmaq);
++
++ /* Falcon requires 128 bit atomic access for this register */
++ FALCON_LOCK_LOCK(nic);
++ falcon_read_q(efhw_kva + offset, &val);
++ FALCON_LOCK_UNLOCK(nic);
++
++ __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH);
++
++ /* is it enabled? */
++ return (val & (1 << RX_DESCQ_EN_LBN))
++ ? 0 : -EAGAIN;
++}
++
++static int falcon_flush_rx_dma_channel(struct efhw_nic *nic, uint dmaq)
++{
++ int rc;
++ rc = __falcon_is_rx_dma_channel_flushed(nic, dmaq);
++ if (rc < 0) {
++ EFHW_ERR("%s: failed %d", __FUNCTION__, rc);
++ return rc;
++ }
++ return __falcon_really_flush_rx_dma_channel(nic, dmaq);
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Falcon specific event callbacks
++ *
++ *--------------------------------------------------------------------*/
++
++int
++falcon_handle_char_event(struct efhw_nic *nic, struct efhw_ev_handler *h,
++ efhw_event_t *ev)
++{
++ EFHW_TRACE("DRIVER EVENT: "FALCON_EVENT_FMT,
++ FALCON_EVENT_PRI_ARG(*ev));
++
++ switch (FALCON_EVENT_DRIVER_SUBCODE(ev)) {
++
++ case TX_DESCQ_FLS_DONE_EV_DECODE:
++ EFHW_TRACE("TX[%d] flushed",
++ (int)FALCON_EVENT_TX_FLUSH_Q_ID(ev));
++#if !defined(__ci_ul_driver__)
++ efhw_handle_txdmaq_flushed(nic, h, ev);
++#endif
++ break;
++
++ case RX_DESCQ_FLS_DONE_EV_DECODE:
++ EFHW_TRACE("RX[%d] flushed",
++ (int)FALCON_EVENT_TX_FLUSH_Q_ID(ev));
++#if !defined(__ci_ul_driver__)
++ efhw_handle_rxdmaq_flushed(nic, h, ev);
++#endif
++ break;
++
++ case SRM_UPD_DONE_EV_DECODE:
++ nic->buf_commit_outstanding =
++ max(0, nic->buf_commit_outstanding - 1);
++ EFHW_TRACE("COMMIT DONE %d", nic->buf_commit_outstanding);
++ break;
++
++ case EVQ_INIT_DONE_EV_DECODE:
++ EFHW_TRACE("EVQ INIT");
++ break;
++
++ case WAKE_UP_EV_DECODE:
++ EFHW_TRACE("WAKE UP");
++ efhw_handle_wakeup_event(nic, h, ev);
++ break;
++
++ case TIMER_EV_DECODE:
++ EFHW_TRACE("TIMER");
++ efhw_handle_timeout_event(nic, h, ev);
++ break;
++
++ case RX_DESCQ_FLSFF_OVFL_EV_DECODE:
++ /* This shouldn't happen. */
++ EFHW_ERR("%s: RX flush fifo overflowed", __FUNCTION__);
++ return -EINVAL;
++
++ default:
++ EFHW_TRACE("UNKOWN DRIVER EVENT: " FALCON_EVENT_FMT,
++ FALCON_EVENT_PRI_ARG(*ev));
++ break;
++ }
++ return 0;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Abstraction Layer Hooks
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_func_ops falcon_char_functional_units = {
++ falcon_nic_close_hardware,
++ falcon_nic_init_hardware,
++ falcon_nic_interrupt,
++ falcon_nic_interrupt_enable,
++ falcon_nic_interrupt_disable,
++ falcon_nic_set_interrupt_moderation,
++ falcon_nic_event_queue_enable,
++ falcon_nic_event_queue_disable,
++ falcon_nic_wakeup_request,
++ falcon_nic_sw_event,
++ falcon_nic_ipfilter_set,
++ falcon_nic_ipfilter_attach,
++ falcon_nic_ipfilter_detach,
++ falcon_nic_ipfilter_clear,
++ falcon_dmaq_tx_q_init,
++ falcon_dmaq_rx_q_init,
++ falcon_dmaq_tx_q_disable,
++ falcon_dmaq_rx_q_disable,
++ falcon_flush_tx_dma_channel,
++ falcon_flush_rx_dma_channel,
++ falcon_nic_buffer_table_set,
++ falcon_nic_buffer_table_set_n,
++ falcon_nic_buffer_table_clear,
++ falcon_nic_buffer_table_commit,
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/falcon_hash.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/falcon_hash.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/falcon_hash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/falcon_hash.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,178 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains EtherFabric NIC hash algorithms implementation.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efhw/debug.h>
++#include <ci/driver/efab/hardware.h>
++
++
++/* this mask is per filter bank hence /2 */
++#define FILTER_MASK(n) ((n) / 2u - 1u)
++
++/*
++ * Main Functions related to the Hash Table Generation
++ * Author: Srinivasaih, Nataraj
++ * Created: Thu May 13:32:41 PDT 2004
++ * $Id: falcon_hash.c,v 1.20 2008/01/29 08:28:56 ok_sasha Exp $
++ */
++/***************************************************************************
++Class Maximum number of Valid address ranges
++ hosts per network
++A 16777214 1.0.0.1 through 9.255.255.254
++ 11.0.0.1 through 126.255.255.254
++B 65534 128.0.0.1 through 172.15.255.254
++ 172.32.0.1 through 191.255.255.254
++C 254 192.0.0.1 through 192.167.255.254
++ 192.169.0.1 through 223.255.255.254
++P 16777214 10.0.0.1 through 10.255.255.254 (10/8)
++ 1048574 172.16.0.1 through 172.31.255.254 (172.16/12)
++ 65534 192.168.0.1 through 192.168.255.254 (192.168/16)
++
++R - 0.0.0.0 through 0.255.255.255
++ (used if host will be assigned a
++ valid address dynamically)
++ 127.0.0.0 through 127.255.255.255
++ (loopback addresses)
++
++P : Private internets only
++R : Reserved
++****************************************************************************/
++
++/* All LE parameters */
++unsigned int
++falcon_hash_get_key(unsigned int src_ip, unsigned int src_port,
++ unsigned int dest_ip, unsigned int dest_port,
++ int tcp, int full)
++{
++
++ unsigned int result = 0;
++ int net_type;
++
++ EFHW_ASSERT(tcp == 0 || tcp == 1);
++ EFHW_ASSERT(full == 0 || full == 1);
++
++ net_type = tcp << 4 | full;
++
++ /* Note that src_ip and src_port ignored if a wildcard filter */
++ switch (net_type) {
++ case 0x01: /* UDP Full */
++ result = ((dest_ip & 0xfffffffe) | (!(dest_ip & 1))) ^
++ (((dest_port << 16) & 0xFFFF0000) |
++ ((src_ip >> 16) & 0x0000FFFF)) ^
++ (((src_ip << 16) & 0xFFFF0000) |
++ ((src_port & 0x0000FFFF)));
++ EFHW_TRACE("falcon_hash_get_key: UDP Full %x", result);
++ break;
++ case 0x00: /* UDP Wild Card */
++ result = ((dest_ip & 0xfffffffe) | (!(dest_ip & 1))) ^
++ (((dest_port << 16) & 0x00000000) |
++ ((src_ip >> 16) & 0x00000000)) ^
++ (((src_ip << 16) & 0x00000000) |
++ ((dest_port & 0x0000FFFF)));
++ EFHW_TRACE("falcon_hash_get_key: UDP Wildcard %x", result);
++ break;
++ case 0x10: /* TCP Wild Card */
++ result = (dest_ip) ^
++ (((dest_port << 16) & 0xFFFF0000) |
++ ((src_ip >> 16) & 0x00000000)) ^
++ (((src_ip << 16) & 0x00000000) |
++ ((src_port & 0x00000000)));
++ EFHW_TRACE("falcon_hash_get_key: TCP Wildcard %x", result);
++ break;
++ case 0x11: /* TCP Full */
++ result = (dest_ip) ^
++ (((dest_port << 16) & 0xFFFF0000) |
++ ((src_ip >> 16) & 0x0000FFFF)) ^
++ (((src_ip << 16) & 0xFFFF0000) |
++ ((src_port & 0x0000FFFF)));
++ EFHW_TRACE("falcon_hash_get_key: TCP Full %x", result);
++ break;
++ default:
++ EFHW_ASSERT(0);
++
++ }
++ return (result);
++}
++
++/* This function generates the First Hash key */
++unsigned int falcon_hash_function1(unsigned int key, unsigned int nfilters)
++{
++
++ unsigned short int lfsr_reg;
++ unsigned int tmp_key;
++ int index;
++
++ unsigned short int lfsr_input;
++ unsigned short int single_bit_key;
++ unsigned short int bit16_lfsr;
++ unsigned short int bit3_lfsr;
++
++ lfsr_reg = 0xFFFF;
++ tmp_key = key;
++
++ /* For Polynomial equation X^16+X^3+1 */
++ for (index = 0; index < 32; index++) {
++ /* Get the bit from key and shift the key */
++ single_bit_key = (tmp_key & 0x80000000) >> 31;
++ tmp_key = tmp_key << 1;
++
++ /* get the Tap bits to XOR operation */
++ bit16_lfsr = (lfsr_reg & 0x8000) >> 15;
++ bit3_lfsr = (lfsr_reg & 0x0004) >> 2;
++
++ /* Get the Input value to the LFSR */
++ lfsr_input = ((bit16_lfsr ^ bit3_lfsr) ^ single_bit_key);
++
++ /* Shift and store out of the two TAPs */
++ lfsr_reg = lfsr_reg << 1;
++ lfsr_reg = lfsr_reg | (lfsr_input & 0x0001);
++
++ }
++
++ lfsr_reg = lfsr_reg & FILTER_MASK(nfilters);
++
++ return lfsr_reg;
++}
++
++/* This function generates the Second Hash */
++unsigned int
++falcon_hash_function2(unsigned int key, unsigned int nfilters)
++{
++ return (unsigned int)(((unsigned long long)key * 2 - 1) &
++ FILTER_MASK(nfilters));
++}
++
++/* This function iterates through the hash table */
++unsigned int
++falcon_hash_iterator(unsigned int hash1, unsigned int hash2,
++ unsigned int n_search, unsigned int nfilters)
++{
++ return ((hash1 + (n_search * hash2)) & FILTER_MASK(nfilters));
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/falcon_mac.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/falcon_mac.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/falcon_mac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/falcon_mac.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,171 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains MACs (Mentor MAC & GDACT1 ) support for Falcon.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efhw/falcon.h>
++#include <ci/driver/efab/hardware.h>
++
++/********************************************************************
++ * Mentor MAC
++ */
++
++#define _PRE(x) GM##x
++
++/*--------------------------------------------------------------------
++ *
++ * Debug Support
++ *
++ *--------------------------------------------------------------------*/
++
++#define MENTOR_MAC_ASSERT_VALID() \
++ EFHW_ASSERT(nic); \
++ EFHW_ASSERT(EFHW_KVA(nic)); \
++ EFHW_ASSERT(_PRE(_CFG1_REG_OFST) == _PRE(_CFG1_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(_CFG2_REG_OFST) == _PRE(_CFG2_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(_IPG_REG_OFST) == _PRE(_IPG_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(_HD_REG_OFST) == _PRE(_HD_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(_MAX_FLEN_REG_OFST) == _PRE(_MAX_FLEN_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(_TEST_REG_OFST) == _PRE(_TEST_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(_ADR1_REG_OFST) == _PRE(_ADR1_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(_ADR2_REG_OFST) == _PRE(_ADR2_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(F_CFG0_REG_OFST) == _PRE(F_CFG0_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(F_CFG1_REG_OFST) == _PRE(F_CFG1_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(F_CFG2_REG_OFST) == _PRE(F_CFG2_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(F_CFG3_REG_OFST) == _PRE(F_CFG3_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(F_CFG4_REG_OFST) == _PRE(F_CFG4_REG_KER_OFST)); \
++ EFHW_ASSERT(_PRE(F_CFG5_REG_OFST) == _PRE(F_CFG5_REG_KER_OFST));
++
++/*! Get MAC current address - i.e not necessarily the one in the EEPROM */
++static inline void mentormac_get_mac_addr(struct efhw_nic *nic)
++{
++ efhw_ioaddr_t mac_kva;
++ uint val1, val2;
++
++ MENTOR_MAC_ASSERT_VALID();
++
++ mac_kva = GM_P0_BASE + EFHW_KVA(nic);
++
++ val1 = readl(mac_kva + _PRE(_ADR1_REG_OFST));
++ val2 = readl(mac_kva + _PRE(_ADR2_REG_OFST));
++
++#if 0
++ nic->mac_addr[0] = (val1 & 0xff000000) >> 24;
++ nic->mac_addr[1] = (val1 & 0x00ff0000) >> 16;
++ nic->mac_addr[2] = (val1 & 0x0000ff00) >> 8;
++ nic->mac_addr[3] = (val1 & 0x000000ff) >> 0;
++ nic->mac_addr[4] = (val2 & 0xff000000) >> 24;
++ nic->mac_addr[5] = (val2 & 0x00ff0000) >> 16;
++#else
++ nic->mac_addr[5] = (val1 & 0xff000000) >> 24;
++ nic->mac_addr[4] = (val1 & 0x00ff0000) >> 16;
++ nic->mac_addr[3] = (val1 & 0x0000ff00) >> 8;
++ nic->mac_addr[2] = (val1 & 0x000000ff) >> 0;
++ nic->mac_addr[1] = (val2 & 0xff000000) >> 24;
++ nic->mac_addr[0] = (val2 & 0x00ff0000) >> 16;
++#endif
++}
++
++
++/********************************************************************
++ * GDACT10 MAC
++ */
++
++/*--------------------------------------------------------------------
++ *
++ * Debug Support
++ *
++ *--------------------------------------------------------------------*/
++
++#define GDACT10_MAC_ASSERT_VALID() \
++ EFHW_ASSERT(nic); \
++ EFHW_ASSERT(EFHW_KVA(nic)); \
++ EFHW_ASSERT(XM_GLB_CFG_REG_P0_OFST == XM_GLB_CFG_REG_KER_P0_OFST); \
++ EFHW_ASSERT(XM_TX_CFG_REG_P0_OFST == XM_TX_CFG_REG_KER_P0_OFST); \
++ EFHW_ASSERT(XM_RX_CFG_REG_P0_OFST == XM_RX_CFG_REG_KER_P0_OFST); \
++ EFHW_ASSERT(MAC0_SPEED_LBN == MAC1_SPEED_LBN); \
++ EFHW_ASSERT(MAC0_SPEED_WIDTH == MAC1_SPEED_WIDTH); \
++ EFHW_ASSERT(MAC0_LINK_STATUS_LBN == MAC1_LINK_STATUS_LBN); \
++ EFHW_ASSERT(MAC0_LINK_STATUS_WIDTH == MAC1_LINK_STATUS_WIDTH); \
++ EFHW_ASSERT(MAC1_BCAD_ACPT_LBN == MAC0_BCAD_ACPT_LBN); \
++ EFHW_ASSERT(MAC1_UC_PROM_LBN == MAC0_UC_PROM_LBN); \
++ EFHW_ASSERT(MAC0_CTRL_REG_KER_OFST == MAC0_CTRL_REG_OFST); \
++ EFHW_ASSERT(MAC1_CTRL_REG_KER_OFST == MAC1_CTRL_REG_OFST); \
++ EFHW_ASSERT(XM_ADR_LO_REG_KER_P0_OFST == XM_ADR_LO_REG_P0_OFST); \
++ EFHW_ASSERT(XM_ADR_HI_REG_KER_P0_OFST == XM_ADR_HI_REG_P0_OFST); \
++ EFHW_ASSERT(XM_RX_PARAM_REG_KER_P0_OFST == XM_RX_PARAM_REG_P0_OFST);
++
++/*--------------------------------------------------------------------
++ *
++ * Information gathering
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Get MAC current address - i.e not necessarily the one in the EEPROM */
++static inline void GDACT10mac_get_mac_addr(struct efhw_nic *nic)
++{
++ uint val1, val2;
++ efhw_ioaddr_t efhw_kva = EFHW_KVA(nic);
++ FALCON_LOCK_DECL;
++
++ GDACT10_MAC_ASSERT_VALID();
++
++ EFHW_ASSERT(XM_ADR_LO_LBN == 0);
++ EFHW_ASSERT(XM_ADR_LO_WIDTH == 32);
++ EFHW_ASSERT(XM_ADR_HI_LBN == 0);
++ EFHW_ASSERT(XM_ADR_HI_WIDTH == 16);
++
++ FALCON_LOCK_LOCK(nic);
++
++ val1 = readl(efhw_kva + XM_ADR_LO_REG_P0_OFST);
++ val2 = readl(efhw_kva + XM_ADR_HI_REG_P0_OFST);
++
++ FALCON_LOCK_UNLOCK(nic);
++
++ /* The HW scores no points for consistency */
++ nic->mac_addr[5] = (val2 & 0x0000ff00) >> 8;
++ nic->mac_addr[4] = (val2 & 0x000000ff) >> 0;
++ nic->mac_addr[3] = (val1 & 0xff000000) >> 24;
++ nic->mac_addr[2] = (val1 & 0x00ff0000) >> 16;
++ nic->mac_addr[1] = (val1 & 0x0000ff00) >> 8;
++ nic->mac_addr[0] = (val1 & 0x000000ff) >> 0;
++}
++
++
++/********************************************************************
++ * Call one or another function
++ */
++
++void falcon_get_mac_addr(struct efhw_nic *nic)
++{
++ if (nic->flags & NIC_FLAG_10G)
++ GDACT10mac_get_mac_addr(nic);
++ else
++ mentormac_get_mac_addr(nic);
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/filter_resource.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/filter_resource.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/filter_resource.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/filter_resource.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,317 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains filters support.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/nic_table.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efhw/falcon.h>
++#include <ci/efrm/vi_resource_manager.h>
++#include <ci/efrm/private.h>
++#include <ci/efrm/filter.h>
++#include <ci/efrm/buffer_table.h>
++
++struct filter_resource_manager {
++ struct efrm_resource_manager rm;
++ struct kfifo *free_ids;
++};
++
++static struct filter_resource_manager *efrm_filter_manager;
++
++void efrm_filter_resource_free(struct filter_resource *frs)
++{
++ struct efhw_nic *nic;
++ int nic_i;
++ int id;
++
++ EFRM_RESOURCE_ASSERT_VALID(&frs->rs, 1);
++
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle));
++
++ /* if we have a PT endpoint */
++ if (NULL != frs->pt) {
++ /* Detach the filter */
++ EFRM_FOR_EACH_NIC_IN_SET(&frs->nic_set, nic_i, nic)
++ efhw_nic_ipfilter_detach(nic, frs->filter_idx);
++
++ /* Release our ref to the PT resource. */
++ EFRM_TRACE("%s: releasing PT resource reference",
++ __FUNCTION__);
++ efrm_vi_resource_release(frs->pt);
++ }
++
++ /* Disable the filter. */
++ EFRM_FOR_EACH_NIC_IN_SET(&frs->nic_set, nic_i, nic)
++ efhw_nic_ipfilter_clear(nic, frs->filter_idx);
++
++ /* Free this filter. */
++ id = EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle);
++ EFRM_VERIFY_EQ(kfifo_put(efrm_filter_manager->free_ids,
++ (unsigned char *)&id, sizeof(id)),
++ sizeof(id));
++
++ EFRM_DO_DEBUG(memset(frs, 0, sizeof(*frs)));
++ kfree(frs);
++}
++EXPORT_SYMBOL(efrm_filter_resource_free);
++
++static void filter_rm_dtor(struct efrm_resource_manager *rm)
++{
++ EFRM_TRACE("filter_rm_dtor");
++
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_filter_manager->rm);
++ EFRM_ASSERT(&efrm_filter_manager->rm == rm);
++
++ kfifo_vfree(efrm_filter_manager->free_ids);
++ EFRM_TRACE("filter_rm_dtor: done");
++}
++
++/**********************************************************************/
++/**********************************************************************/
++/**********************************************************************/
++
++int efrm_create_filter_resource_manager(struct efrm_resource_manager **rm_out)
++{
++ int rc;
++
++ EFRM_ASSERT(rm_out);
++
++ efrm_filter_manager =
++ kmalloc(sizeof(struct filter_resource_manager), GFP_KERNEL);
++ if (efrm_filter_manager == 0)
++ return -ENOMEM;
++ memset(efrm_filter_manager, 0, sizeof(*efrm_filter_manager));
++
++ rc = efrm_resource_manager_ctor(&efrm_filter_manager->rm,
++ filter_rm_dtor, "FILTER",
++ EFRM_RESOURCE_FILTER, 0);
++ if (rc < 0)
++ goto fail1;
++
++ /* Create a pool of free instances */
++ rc = efrm_kfifo_id_ctor(&efrm_filter_manager->free_ids,
++ 0, EFHW_IP_FILTER_NUM,
++ &efrm_filter_manager->rm.rm_lock);
++ if (rc != 0)
++ goto fail2;
++
++ *rm_out = &efrm_filter_manager->rm;
++ EFRM_TRACE("%s: filter resources created - %d IDs",
++ __FUNCTION__, kfifo_len(efrm_filter_manager->free_ids));
++ return 0;
++
++fail2:
++ efrm_resource_manager_dtor(&efrm_filter_manager->rm);
++fail1:
++ memset(efrm_filter_manager, 0, sizeof(*efrm_filter_manager));
++ kfree(efrm_filter_manager);
++ return rc;
++
++}
++
++/*--------------------------------------------------------------------
++ *!
++ * Called to set/change the PT endpoint of a filter
++ *
++ * Example of use is TCP helper when it finds a wildcard IP filter
++ * needs to change which application it delivers traffic to
++ *
++ * \param frs filter resource
++ * \param pt_handle handle of new PT endpoint
++ *
++ * \return standard error codes
++ *
++ *--------------------------------------------------------------------*/
++int
++efrm_filter_resource_set_ptresource(struct filter_resource *frs,
++ struct vi_resource *ptrs)
++{
++ int rc, pti, nic_i;
++ struct efhw_nic *nic;
++
++ EFRM_ASSERT(frs);
++
++ /* if filter is attached to a valid PT endpoint */
++ if (NULL != frs->pt) {
++
++ EFRM_TRACE("%s: detaching PT resource " EFRM_RESOURCE_FMT
++ " from filter ",
++ __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle));
++ /* Detach the filter */
++ EFRM_FOR_EACH_NIC_IN_SET(&frs->nic_set, nic_i, nic)
++ efhw_nic_ipfilter_detach(nic, frs->filter_idx);
++
++ /* release reference */
++ efrm_vi_resource_release(frs->pt);
++ frs->pt = NULL;
++ }
++
++ if (ptrs != NULL) {
++ /* get PT endpoint index */
++ EFRM_RESOURCE_ASSERT_VALID(&ptrs->rs, 0);
++ EFRM_ASSERT(EFRM_RESOURCE_TYPE(ptrs->rs.rs_handle) ==
++ EFRM_RESOURCE_VI);
++ pti = EFRM_RESOURCE_INSTANCE(ptrs->rs.rs_handle);
++ if (pti == 0) {
++ EFRM_ERR("%s: cannot filter for channel 0",
++ __FUNCTION__);
++ rc = -EINVAL;
++ goto fail2;
++ }
++ frs->pt = ptrs;
++ EFRM_TRACE("%s: attaching PT resource " EFRM_RESOURCE_FMT
++ " to filter",
++ __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(frs->pt->rs.rs_handle));
++ EFRM_FOR_EACH_NIC_IN_SET(&frs->nic_set, nic_i, nic)
++ efhw_nic_ipfilter_attach(nic, frs->filter_idx, pti);
++ efrm_vi_resource_ref(frs->pt);
++ }
++ return 0;
++
++fail2:
++ efrm_vi_resource_release(frs->pt);
++ return rc;
++}
++EXPORT_SYMBOL(efrm_filter_resource_set_ptresource);
++
++int efrm_filter_resource_clear(struct filter_resource *frs)
++{
++ struct efhw_nic *nic;
++ int nic_i;
++
++ EFRM_ASSERT(frs);
++ EFRM_FOR_EACH_NIC_IN_SET(&frs->nic_set, nic_i, nic)
++ efhw_nic_ipfilter_clear(nic, frs->filter_idx);
++
++ return 0;
++}
++EXPORT_SYMBOL(efrm_filter_resource_clear);
++
++int
++__efrm_filter_resource_set(struct filter_resource *frs, int type,
++ unsigned saddr, uint16_t sport,
++ unsigned daddr, uint16_t dport)
++{
++ struct efhw_nic *nic;
++ int nic_i, rc = 0;
++ unsigned instance = EFRM_RESOURCE_INSTANCE(frs->pt->rs.rs_handle);
++
++ EFRM_ASSERT(frs);
++ EFRM_ASSERT(frs->pt);
++
++ if (efrm_nic_table.a_nic->devtype.variant >= 'B') {
++ /* Scatter setting must match the setting for
++ * the corresponding RX queue */
++ if (!(frs->pt->flags & EFHW_VI_JUMBO_EN))
++ type |= EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK;
++ }
++
++ EFRM_FOR_EACH_NIC_IN_SET(&frs->nic_set, nic_i, nic)
++ if (rc >= 0)
++ rc = efhw_nic_ipfilter_set(nic, type, &frs->filter_idx,
++ instance,
++ saddr, sport, daddr, dport);
++
++ return rc;
++}
++EXPORT_SYMBOL(__efrm_filter_resource_set);;
++
++int
++efrm_filter_resource_alloc(struct vi_resource *vi_parent,
++ struct filter_resource **frs_out)
++{
++ struct efhw_nic *nic;
++ int nic_i, rc, instance;
++ struct filter_resource *frs;
++
++ EFRM_ASSERT(frs_out);
++ EFRM_ASSERT(efrm_filter_manager);
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_filter_manager->rm);
++ EFRM_ASSERT(vi_parent == NULL ||
++ EFRM_RESOURCE_TYPE(vi_parent->rs.rs_handle) ==
++ EFRM_RESOURCE_VI);
++
++ /* Allocate resource data structure. */
++ frs = kmalloc(sizeof(struct filter_resource), GFP_KERNEL);
++ if (!frs)
++ return -ENOMEM;
++ efrm_nic_set_clear(&frs->nic_set);
++
++ /* Allocate an instance. */
++ rc = kfifo_get(efrm_filter_manager->free_ids,
++ (unsigned char *)&instance, sizeof(instance));
++ if (rc != sizeof(instance)) {
++ EFRM_TRACE("%s: out of instances", __FUNCTION__);
++ EFRM_ASSERT(rc == 0);
++ rc = -EBUSY;
++ goto fail1;
++ }
++
++ /* Initialise the resource DS. */
++ efrm_resource_init(&frs->rs, EFRM_RESOURCE_FILTER, instance);
++ frs->pt = vi_parent;
++ if (frs->pt)
++ efrm_vi_resource_ref(frs->pt);
++ frs->filter_idx = -1;
++ EFRM_FOR_EACH_NIC(nic_i, nic)
++ efrm_nic_set_write(&frs->nic_set, nic_i, true);
++
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " Q %d idx %x",
++ __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle),
++ vi_parent == NULL ? -1 :
++ EFRM_RESOURCE_INSTANCE(vi_parent->rs.rs_handle),
++ frs->filter_idx);
++
++ /* Put it into the resource manager's table. */
++ rc = efrm_resource_manager_insert(&frs->rs);
++ if (rc != 0) {
++ if (atomic_dec_and_test(&frs->rs.rs_ref_count))
++ efrm_filter_resource_free(frs);
++ return rc;
++ }
++
++ *frs_out = frs;
++ return 0;
++
++fail1:
++ memset(frs, 0, sizeof(*frs));
++ kfree(frs);
++ return rc;
++}
++EXPORT_SYMBOL(efrm_filter_resource_alloc);
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/iobufset_resource.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/iobufset_resource.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/iobufset_resource.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/iobufset_resource.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,373 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains non-contiguous I/O buffers support.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/nic_table.h>
++#include <ci/efhw/iopage.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efrm/private.h>
++#include <ci/efrm/iobufset.h>
++#include <ci/efrm/vi_resource_manager.h>
++#include <ci/efrm/buffer_table.h>
++
++#define EFRM_IOBUFSET_MAX_NUM_INSTANCES 0x00010000
++
++struct iobufset_resource_manager {
++ struct efrm_resource_manager rm;
++ struct kfifo *free_ids;
++};
++
++struct iobufset_resource_manager *efrm_iobufset_manager;
++
++#define iobsrs(rs1) iobufset_resource(rs1)
++
++/* Returns size of iobufset resource data structure. */
++static inline size_t iobsrs_size(int no_pages)
++{
++ return offsetof(struct iobufset_resource, bufs) +
++ no_pages * sizeof(efhw_iopage_t);
++}
++
++void efrm_iobufset_resource_free(struct iobufset_resource *rs)
++{
++ unsigned int no_pages;
++ unsigned int i;
++ int id;
++
++ EFRM_RESOURCE_ASSERT_VALID(&rs->rs, 1);
++ no_pages = rs->n_bufs;
++
++ if (rs->buf_tbl_alloc.base != (unsigned)-1)
++ efrm_buffer_table_free(&rs->buf_tbl_alloc);
++
++ /* see comment on call to efhw_iopage_alloc in the alloc routine above
++ for discussion on use of efrm_nic_table.a_nic here */
++ EFRM_ASSERT(efrm_nic_table.a_nic);
++ if (rs->order == 0) {
++ for (i = 0; i < rs->n_bufs; ++i)
++ efhw_iopage_free(efrm_nic_table.a_nic, &rs->bufs[i]);
++ } else {
++ /* it is important that this is executed in increasing page
++ * order because some implementations of
++ * efhw_iopages_init_from_iopage() assume this */
++ for (i = 0; i < rs->n_bufs;
++ i += rs->pages_per_contiguous_chunk) {
++ efhw_iopages_t iopages;
++ efhw_iopages_init_from_iopage(&iopages, &rs->bufs[i],
++ rs->order);
++ efhw_iopages_free(efrm_nic_table.a_nic, &iopages);
++ }
++ }
++
++ /* free the instance number */
++ id = EFRM_RESOURCE_INSTANCE(rs->rs.rs_handle);
++ EFRM_VERIFY_EQ(kfifo_put(efrm_iobufset_manager->free_ids,
++ (unsigned char *)&id, sizeof(id)), sizeof(id));
++
++ efrm_vi_resource_release(rs->evq);
++
++ EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs)));
++ if (iobsrs_size(no_pages) < PAGE_SIZE) {
++ kfree(rs);
++ } else {
++ vfree(rs);
++ }
++}
++EXPORT_SYMBOL(efrm_iobufset_resource_free);
++
++int
++efrm_iobufset_resource_alloc(int32_t n_pages,
++ int32_t pages_per_contiguous_chunk,
++ struct vi_resource *vi_evq,
++ bool phys_addr_mode,
++ uint32_t faultonaccess,
++ struct iobufset_resource **iobrs_out)
++{
++ struct iobufset_resource *iobrs;
++ int rc, instance, object_size;
++ unsigned int i;
++
++ EFRM_ASSERT(iobrs_out);
++ EFRM_ASSERT(efrm_iobufset_manager);
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_iobufset_manager->rm);
++ EFRM_RESOURCE_ASSERT_VALID(&vi_evq->rs, 0);
++ EFRM_ASSERT(EFRM_RESOURCE_TYPE(vi_evq->rs.rs_handle) ==
++ EFRM_RESOURCE_VI);
++ EFRM_ASSERT(efrm_nic_table.a_nic);
++
++ /* allocate the resource data structure. */
++ object_size = iobsrs_size(n_pages);
++ if (object_size < PAGE_SIZE) {
++ /* this should be OK from a tasklet */
++ /* Necessary to do atomic alloc() as this
++ can be called from a weird-ass iSCSI context that is
++ !in_interrupt but is in_atomic - See BUG3163 */
++ iobrs = kmalloc(object_size, GFP_ATOMIC);
++ } else { /* can't do this within a tasklet */
++#ifndef NDEBUG
++ if (in_interrupt() || in_atomic()) {
++ EFRM_ERR("%s(): alloc->u.iobufset.in_n_pages=%d",
++ __FUNCTION__, n_pages);
++ EFRM_ASSERT(!in_interrupt());
++ EFRM_ASSERT(!in_atomic());
++ }
++#endif
++ iobrs = (struct iobufset_resource *) vmalloc(object_size);
++ }
++ if (iobrs == 0) {
++ rc = -ENOMEM;
++ goto fail1;
++ }
++
++ /* Allocate an instance number. */
++ rc = kfifo_get(efrm_iobufset_manager->free_ids,
++ (unsigned char *)&instance, sizeof(instance));
++ if (rc != sizeof(instance)) {
++ EFRM_TRACE("%s: out of instances", __FUNCTION__);
++ EFRM_ASSERT(rc == 0);
++ rc = -EBUSY;
++ goto fail3;
++ }
++
++ efrm_resource_init(&iobrs->rs, EFRM_RESOURCE_IOBUFSET, instance);
++
++ iobrs->evq = vi_evq;
++ efrm_vi_resource_ref(iobrs->evq);
++
++ iobrs->n_bufs = n_pages;
++ iobrs->pages_per_contiguous_chunk = pages_per_contiguous_chunk;
++ iobrs->order = fls(iobrs->pages_per_contiguous_chunk - 1);
++ iobrs->faultonaccess = faultonaccess;
++
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %u pages", __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle), iobrs->n_bufs);
++
++ /* Allocate the iobuffers. */
++ if (iobrs->order == 0) {
++ /* make sure iobufs are in a known state in case we don't
++ * finish our allocation */
++ for (i = 0; i < iobrs->n_bufs; ++i)
++ memset(&iobrs->bufs[i], 0, sizeof(iobrs->bufs[i]));
++
++ for (i = 0; i < iobrs->n_bufs; ++i) {
++ /* due to bug2426 we have to specifiy a NIC when
++ * allocating a DMAable page, which is a bit messy.
++ * For now we assume that if the page is suitable
++ * (e.g. DMAable) by one nic (efrm_nic_table.a_nic),
++ * it is suitable for all NICs.
++ * XXX I bet that breaks in Solaris.
++ */
++ rc = efhw_iopage_alloc(efrm_nic_table.a_nic,
++ &iobrs->bufs[i]);
++ if (rc < 0) {
++ EFRM_ERR("%s: failed (rc %d) to allocate "
++ "page (i=%u)", __FUNCTION__, rc, i);
++ goto fail4;
++ }
++ }
++ } else {
++ efhw_iopages_t iopages;
++ unsigned j;
++
++ /* make sure iobufs are in a known state in case we don't
++ * finish our allocation */
++ for (i = 0; i < iobrs->n_bufs; ++i)
++ memset(&iobrs->bufs[i], 0, sizeof(iobrs->bufs[i]));
++
++ for (i = 0; i < iobrs->n_bufs;
++ i += iobrs->pages_per_contiguous_chunk) {
++ rc = efhw_iopages_alloc(efrm_nic_table.a_nic,
++ &iopages, iobrs->order);
++ if (rc < 0) {
++ EFRM_ERR("%s: failed (rc %d) to allocate "
++ "pages (i=%u order %d)",
++ __FUNCTION__, rc, i, iobrs->order);
++ goto fail4;
++ }
++ for (j = 0; j < iobrs->pages_per_contiguous_chunk;
++ j++) {
++ /* some implementation of
++ * efhw_iopage_init_from_iopages() rely on
++ * this function being called for
++ * _all_ pages in the chunk */
++ efhw_iopage_init_from_iopages(
++ &iobrs->bufs[i + j],
++ &iopages, j);
++ }
++ }
++ }
++
++ iobrs->buf_tbl_alloc.base = (unsigned)-1;
++
++ if (!phys_addr_mode) {
++ unsigned instance = EFAB_VI_RESOURCE_INSTANCE(iobrs->evq);
++ /* Allocate space in the NIC's buffer table. */
++ rc = efrm_buffer_table_alloc(fls(iobrs->n_bufs - 1),
++ &iobrs->buf_tbl_alloc);
++ if (rc < 0) {
++ EFRM_ERR("%s: failed (%d) to alloc %d buffer table "
++ "entries", __FUNCTION__, rc, iobrs->n_bufs);
++ goto fail5;
++ }
++ EFRM_ASSERT(((unsigned)1 << iobrs->buf_tbl_alloc.order) >=
++ (unsigned)iobrs->n_bufs);
++
++ /* Initialise the buffer table entries. */
++ for (i = 0; i < iobrs->n_bufs; ++i) {
++ /*\ ?? \TODO burst them! */
++ efrm_buffer_table_set(&iobrs->buf_tbl_alloc, i,
++ efhw_iopage_dma_addr(&iobrs->
++ bufs[i]),
++ instance);
++ }
++ efrm_buffer_table_commit();
++ }
++
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %d pages @ "
++ EFHW_BUFFER_ADDR_FMT, __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle),
++ iobrs->n_bufs, EFHW_BUFFER_ADDR(iobrs->buf_tbl_alloc.base,
++ 0));
++
++ /* Put it into the resource manager's table. */
++ rc = efrm_resource_manager_insert(&iobrs->rs);
++ if (rc != 0) {
++ if (atomic_dec_and_test(&iobrs->rs.rs_ref_count))
++ efrm_iobufset_resource_free(iobrs);
++ return rc;
++ }
++
++ *iobrs_out = iobrs;
++ return 0;
++
++fail5:
++ i = iobrs->n_bufs;
++fail4:
++ /* see comment on call to efhw_iopage_alloc above for a discussion
++ * on use of efrm_nic_table.a_nic here */
++ if (iobrs->order == 0) {
++ while (i--) {
++ efhw_iopage_t *page = &iobrs->bufs[i];
++ efhw_iopage_free(efrm_nic_table.a_nic, page);
++ }
++ } else {
++ unsigned int j;
++ for (j = 0; j < i; j += iobrs->pages_per_contiguous_chunk) {
++ efhw_iopages_t iopages;
++
++ EFRM_ASSERT(j % iobrs->pages_per_contiguous_chunk
++ == 0);
++ /* it is important that this is executed in increasing
++ * page order because some implementations of
++ * efhw_iopages_init_from_iopage() assume this */
++ efhw_iopages_init_from_iopage(&iopages,
++ &iobrs->bufs[j],
++ iobrs->order);
++ efhw_iopages_free(efrm_nic_table.a_nic, &iopages);
++ }
++ }
++ efrm_vi_resource_release(iobrs->evq);
++fail3:
++ if (object_size < PAGE_SIZE) {
++ kfree(iobrs);
++ } else {
++ vfree(iobrs);
++ }
++fail1:
++ return rc;
++}
++EXPORT_SYMBOL(efrm_iobufset_resource_alloc);
++
++static void iobufset_rm_dtor(struct efrm_resource_manager *rm)
++{
++ EFRM_ASSERT(&efrm_iobufset_manager->rm == rm);
++ kfifo_vfree(efrm_iobufset_manager->free_ids);
++}
++
++int
++efrm_create_iobufset_resource_manager(struct efrm_resource_manager **rm_out)
++{
++ int rc, max;
++
++ EFRM_ASSERT(rm_out);
++
++ efrm_iobufset_manager =
++ kmalloc(sizeof(*efrm_iobufset_manager), GFP_KERNEL);
++ if (efrm_iobufset_manager == 0)
++ return -ENOMEM;
++ memset(efrm_iobufset_manager, 0, sizeof(*efrm_iobufset_manager));
++
++ /*
++ * Bug 1145, 1370: We need to set initial size of both the resource
++ * table and instance id table so they never need to grow as we
++ * want to be allocate new iobufset at tasklet time. Lets make
++ * a pessimistic guess at maximum number of iobufsets possible.
++ * Could be less because
++ * - jumbo frames have same no of packets per iobufset BUT more
++ * pages per buffer
++ * - buffer table entries used independently of iobufsets by
++ * sendfile
++ *
++ * Based on TCP/IP stack setting of PKTS_PER_SET_S=5 ...
++ * - can't use this define here as it breaks the layering.
++ */
++#define MIN_PAGES_PER_IOBUFSET (1 << 4)
++
++ max = efrm_buffer_table_size() / MIN_PAGES_PER_IOBUFSET;
++ max = min_t(int, max, EFRM_IOBUFSET_MAX_NUM_INSTANCES);
++
++ rc = efrm_kfifo_id_ctor(&efrm_iobufset_manager->free_ids,
++ 0, max, &efrm_iobufset_manager->rm.rm_lock);
++ if (rc != 0)
++ goto fail1;
++
++ rc = efrm_resource_manager_ctor(&efrm_iobufset_manager->rm,
++ iobufset_rm_dtor, "IOBUFSET",
++ EFRM_RESOURCE_IOBUFSET, max);
++ if (rc < 0)
++ goto fail2;
++
++ *rm_out = &efrm_iobufset_manager->rm;
++ return 0;
++
++fail2:
++ kfifo_vfree(efrm_iobufset_manager->free_ids);
++fail1:
++ EFRM_DO_DEBUG(memset(efrm_iobufset_manager, 0,
++ sizeof(*efrm_iobufset_manager)));
++ kfree(efrm_iobufset_manager);
++ return rc;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/iopage.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/iopage.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/iopage.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/iopage.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,101 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides Linux-specific implementation for iopage API used
++ * from efhw library.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/driver/resource/linux_efhw_nic.h>
++#include "kernel_compat.h"
++#include <ci/efhw/common_sysdep.h> /* for dma_addr_t */
++
++int efhw_iopage_alloc(struct efhw_nic *nic, efhw_iopage_t *p)
++{
++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
++ dma_addr_t handle;
++ void *kva;
++
++ kva = efrm_pci_alloc_consistent(lnic->pci_dev, PAGE_SIZE,
++ &handle);
++ if (kva == 0)
++ return -ENOMEM;
++
++ EFHW_ASSERT((handle & ~PAGE_MASK) == 0);
++
++ memset((void *)kva, 0, PAGE_SIZE);
++ efhw_page_init_from_va(&p->p, kva);
++
++ p->dma_addr = handle;
++
++ return 0;
++}
++
++void efhw_iopage_free(struct efhw_nic *nic, efhw_iopage_t *p)
++{
++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
++ EFHW_ASSERT(efhw_page_is_valid(&p->p));
++
++ efrm_pci_free_consistent(lnic->pci_dev, PAGE_SIZE,
++ efhw_iopage_ptr(p), p->dma_addr);
++}
++
++int efhw_iopages_alloc(struct efhw_nic *nic, efhw_iopages_t *p, unsigned order)
++{
++ unsigned bytes = 1u << (order + PAGE_SHIFT);
++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
++ dma_addr_t handle;
++ caddr_t addr;
++ int gfp_flag;
++
++ /* Set __GFP_COMP if available to make reference counting work.
++ * This is recommended here:
++ * http://www.forbiddenweb.org/viewtopic.php?id=83167&page=4#348331
++ */
++ gfp_flag = ((in_atomic() ? GFP_ATOMIC : GFP_KERNEL) | __GFP_COMP);
++ addr = efrm_dma_alloc_coherent(&lnic->pci_dev->dev, bytes, &handle,
++ gfp_flag);
++ if (addr == NULL)
++ return -ENOMEM;
++
++ EFHW_ASSERT((handle & ~PAGE_MASK) == 0);
++
++ p->order = order;
++ p->dma_addr = handle;
++ p->kva = addr;
++
++ return 0;
++}
++
++void efhw_iopages_free(struct efhw_nic *nic, efhw_iopages_t *p)
++{
++ unsigned bytes = 1u << (p->order + PAGE_SHIFT);
++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
++
++ efrm_dma_free_coherent(&lnic->pci_dev->dev, bytes,
++ (void *)p->kva, p->dma_addr);
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/kernel_compat.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/kernel_compat.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/kernel_compat.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/kernel_compat.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,584 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides compatibility layer for various Linux kernel versions
++ * (starting from 2.6.9 RHEL kernel).
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#define IN_KERNEL_COMPAT_C
++#include <linux/types.h>
++#include <ci/efrm/debug.h>
++#include "kernel_compat.h"
++
++/* Set this to 1 to enable very basic counting of iopage(s) allocations, then
++ * call dump_iopage_counts() to show the number of current allocations of
++ * orders 0-7.
++ */
++#define EFRM_IOPAGE_COUNTS_ENABLED 0
++
++
++
++/* I admit that it's a bit ugly going straight to the field, but it
++ * seems easiest given that get_page followed by put_page on a page
++ * with PG_reserved set will increment the ref count on 2.6.14 and
++ * below, but not 2.6.15. Also, RedHat have hidden put_page_testzero
++ * in a header file which produces warnings when compiled. This
++ * doesn't agree with our use of -Werror.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
++# define page_count_field(pg) ((pg)->count)
++#else
++# define page_count_field(pg) ((pg)->_count)
++#endif
++
++#define inc_page_count(page) atomic_inc(&page_count_field(page))
++#define dec_page_count(page) atomic_dec(&page_count_field(page))
++
++/* Bug 5531: set_page_count doesn't work if the new page count is an
++ * expression. */
++#define ci_set_page_count(page, n) set_page_count(page, (n))
++
++ /* Bug 3965: Gak! Reference counts just don't work on memory
++ * allocated through pci_alloc_consistent. Different versions and
++ * architectures do different things. There are several interacting
++ * bugs/features which have been described below and then summarised
++ * in a table for each kernel version. For each feature, there is a
++ * question, a short description, a hint at how to examine the
++ * kernel code for this feature and a description of the keys in the
++ * table.
++ *
++ * A. Is PG_compound set on multi-page allocations?
++ *
++ * When a multi-page allocation succeeds, the kernel sets the
++ * reference count of the first page to one and the count of the
++ * remaining pages to zero. This is an immediate problem because
++ * if these pages are mapped into user space, the VM will do
++ * get_page followed by put_page, at which point the reference
++ * count will return to zero and the page will be freed.
++ * PG_compound was introduced in 2.6.0 and back-ported to rhel3
++ * kernels. When it is set, all the pages have a pointer to the
++ * first page so that they can share the reference count. If
++ * PG_compound is set, calling get_page(pg+1) can change
++ * page_count(pg). It was originally set on all multi-page
++ * allocations, but later only set if the __GFP_COMP flag was
++ * provided to the allocator.
++ *
++ * See mm/page_alloc.c
++ * Does prep_compound_page get called when __GFP_COMP not set?
++ *
++ * Keys:
++ * NotDef - prep_compound_page and PG_compound are not defined.
++ * Comp - prep_compound_page is called for any multi-page allocation.
++ * Opt - prep_compound_page is only called if __GFP_COMP is set.
++ * OptInv - prep_compound_page is only called if __GFP_NO_COMP is not set.
++ *
++ * B. Are bounce buffers ever used to satisfy pci_alloc_consistent?
++ * (x86_64 only)
++ *
++ * 2.6 kernels introduced bounce buffers on x86_64 machines to access
++ * memory above 4G when using the DMA mapping API. At some point,
++ * code was added to allow pci_alloc_consistent/dma_alloc_coherent to
++ * allocate memory from the bounce buffers if the general purpose
++ * allocator produced memory which wasn't suitable. Such memory can
++ * be recognised by the PG_reserved bit being set. At a later point,
++ * the __GFP_DMA32 flag was added and used to restrict the allocator
++ * to below 4G. The effect of this later change was that 4G capable
++ * cards would no longer get memory from the bounce buffers, although
++ * a card which can address less than 4G might get memory from the
++ * bounce buffers.
++ *
++ * See dma_alloc_coherent or pci_alloc_consistent in
++ * arch/x86_64/kernel/pci-gart.c or arch/x86/kernel/pci-dma_64.c
++ * Is (gfp |= GFP_DMA32) before dma_alloc_pages?
++ * Is swiotlb_alloc_coherent called?
++ *
++ * Keys:
++ * NU - bounce buffers are Never Used
++ * Used - bounce buffers are sometimes used
++ *
++ * C. Does munmap decrement the reference count of a PG_reserved page?
++ *
++ * Originally, the munmap code would not decrement the reference count
++ * of a page which had PG_reserved set. At some point in the 2.6
++ * series, VM_PFNMAP was introduced and could be set on a vma to
++ * indicate that no pages in that vma should have the reference count
++ * decremented (unless they are copy-on-write copies). At that point,
++ * the check for PG_reserved pages in the munmap code path was
++ * removed. Some hackery in vm_normal_page means that a VM_PFNMAP vma
++ * must map contiguous physical pages. As a result, such pages should
++ * be mapped during mmap using remap_pfn_range (for an example, see
++ * drivers/char/mem.c).
++ *
++ * In 2.6 kernels: See release_pages in mm/swap.c
++ * Does PageReserved get tested?
++ * In 2.6 kernels: See mm/memory.c
++ * Is VM_PFNMAP used?
++ * In 2.4 kernels: See __free_pte in mm/memory.c
++ * Does PageReserved get tested?
++ * In 2.4 kernels: See __free_pages in mm/page_alloc.c
++ * Does PageReserved get tested?
++ *
++ * Keys:
++ * resv - The reference count is not touched for PG_reserved pages.
++ * pfnmap - The VM_PFNMAP flag is checked instead of PG_reserved.
++ *
++ * D. Does munmap honour the PG_compound bit?
++ *
++ * When PG_compound was originally introduced, the munmap code path
++ * didn't check it before decrementing the reference count on the
++ * page. As a result, the wrong reference count would be updated if a
++ * PG_compound page was ever mapped into user space.
++ *
++ * In 2.6 kernels: See release_pages in mm/swap.c
++ * Does PageCompound get tested?
++ * In 2.4 kernels: See __free_pages in mm/page_alloc.c
++ * Does PageCompound get tested?
++ *
++ * Keys:
++ * NotHon - The PG_compound bit isn't honoured by munmap.
++ * Hon - The PG_compound bit is honoured by munmap.
++ *
++ * OS A B C D
++ * 2.4.18 NotDef NU resv NotHon
++ * 2.4.29 NotDef NU resv NotHon
++ * 2.4.20-31.9 rhl9 NotDef NU resv NotHon
++ *
++ * 2.4.21-4.EL rhel3 Comp NU resv Hon
++ * 2.4.21-15.EL rhel3 Comp NU resv Hon
++ * 2.4.21-32.EL rhel3 Comp NU resv Hon
++ * 2.4.21-40.EL rhel3 Comp NU resv Hon
++ *
++ * 2.6.0 Comp NU resv NotHon
++ *
++ * 2.6.5-7.97 sles9 OptInv NU resv NotHon
++ * 2.6.9 rhel4 Opt NU resv NotHon
++ *
++ * 2.6.11 fc4 ? ? ? ?
++ * 2.6.12 fc4 Opt Used resv NotHon
++ * 2.6.13 Opt Used resv NotHon
++ *
++ * 2.6.15 Opt NU pfnmap NotHon
++ *
++ * 2.6.16 Opt NU pfnmap Hon
++ * 2.6.16.9 Opt NU pfnmap Hon
++ * 2.6.17.2 Opt NU pfnmap Hon
++ * 2.6.24-rc7 k.org Opt NU pfnmap Hon
++ *
++ * This LKML thread gives some low down on mapping pages into user
++ * space and using DMA.
++ * http://www.forbiddenweb.org/viewtopic.php?id=83167&page=1
++ *
++ * There is no problem with single page allocations (until some
++ * kernel hands us a PG_reserved page and expects us to use
++ * VM_PFNMAP on the vma).
++ *
++ * Bug 5450: Most kernels set the reference count to one on the
++ * first sub-page of a high-order page allocation and zero on
++ * subsequent sub-pages. Some kernels, however, set the page count
++ * to one on all the sub-pages. The SLES 9 range are affected, as
++ * are kernels built without CONFIG_MMU defined.
++ *
++ * Possible strategies for multi-page allocations:
++ *
++ * EFRM_MMAP_USE_COMPOUND
++ * 1. Allocate a compound page. Reference counting should then work
++ * on the whole allocation. This is a good theory, but is broken
++ * by bug/feature D (above).
++ *
++ * EFRM_MMAP_USE_SPLIT
++ * 2. Convert the multi-page allocation to many single page
++ * allocations. This involves incrementing the reference counts
++ * and clearing PG_compound on all the pages (including the
++ * first). The references should be released _after_ calling
++ * pci_free_consistent so that that call doesn't release the
++ * memory.
++ *
++ * EFRM_MMAP_USE_INCREMENT
++ * 3. Increment the reference count on all the pages after
++ * allocating and decrement them again before freeing. This gets
++ * round the zero reference count problem. It doesn't handle the
++ * case where someone else is holding a reference to one of our
++ * pages when we free the pages, but we think VM_IO stops this
++ * from happening.
++ */
++
++/* Should we use strategy 1? This can be forced on us by the OS. */
++#if defined(PG_compound)
++#define EFRM_MMAP_USE_COMPOUND 1
++#else
++#define EFRM_MMAP_USE_COMPOUND 0
++#endif
++
++/* Should we use strategy 2? This can be used even if strategy 1 is
++ * used. */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++#define EFRM_MMAP_USE_SPLIT 1
++#else
++#define EFRM_MMAP_USE_SPLIT 0
++#endif
++
++/* Should we use strategy 3? There's no point doing this if either
++ * strategy 1 or strategy 2 is used. */
++#if !EFRM_MMAP_USE_COMPOUND && !EFRM_MMAP_USE_SPLIT
++#error "We shouldn't have to use this strategy."
++#define EFRM_MMAP_USE_INCREMENT 1
++#else
++#define EFRM_MMAP_USE_INCREMENT 0
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
++#define EFRM_MMAP_RESET_REFCNT 1
++#else
++#define EFRM_MMAP_RESET_REFCNT 0
++#endif
++
++/* NB. 2.6.17 has renamed SetPageCompound to __SetPageCompound and
++ * ClearPageCompound to __ClearPageCompound. */
++#if ((defined(PageCompound) != defined(PG_compound)) || \
++ (defined(SetPageCompound) != defined(PG_compound) && \
++ defined(__SetPageCompound) != defined(PG_compound)) || \
++ (defined(ClearPageCompound) != defined(PG_compound) && \
++ defined(__ClearPageCompound) != defined(PG_compound)) || \
++ (defined(__GFP_COMP) && !defined(PG_compound)))
++#error Mismatch of defined page-flags.
++#endif
++
++extern int use_pci_alloc; /* Use pci_alloc_consistent to alloc iopages */
++
++/****************************************************************************
++ *
++ * allocate a buffer suitable for DMA to/from the NIC
++ *
++ ****************************************************************************/
++
++static inline void pci_mmap_pages_hack_after_alloc(caddr_t kva, unsigned order)
++{
++ unsigned pfn = __pa(kva) >> PAGE_SHIFT;
++ struct page *start_pg = pfn_to_page(pfn);
++#if !defined(NDEBUG) || EFRM_MMAP_USE_SPLIT
++ struct page *end_pg = start_pg + (1 << order);
++ struct page *pg;
++#endif
++
++ /* Compound pages don't get created for order 0 pages and there's no
++ * fixing up needs to be done. */
++ if (order == 0)
++ return;
++
++ /* If we've been given a reserved page then it must have come from
++ * the bounce buffer pool. */
++ if (PageReserved(start_pg)) {
++#if defined(VM_PFNMAP) || !defined(__x86_64__)
++ /* Kernel allocated reserved pages when not expected */
++ BUG();
++#endif
++ return;
++ }
++
++ /* Check the page count and PG_compound bit. */
++#ifndef NDEBUG
++# if defined(PG_compound)
++ EFRM_ASSERT(PageCompound(start_pg) == EFRM_MMAP_USE_COMPOUND);
++# endif
++ EFRM_ASSERT(page_count(start_pg) == 1);
++
++ {
++ /* Some kernels have the page count field hold (ref_count-1)
++ * rather than (ref_count). This is so that decrementing the
++ * reference count to "zero" causes the internal value to change
++ * from 0 to -1 which sets the carry flag. Other kernels store
++ * the real reference count value in the obvious way. We handle
++ * this here by reading the reference count field of the first
++ * page, which is always 1. */
++ int pg_count_zero;
++ pg_count_zero = atomic_read(&page_count_field(start_pg)) - 1;
++ for (pg = start_pg + 1; pg < end_pg; pg++) {
++ int pg_count;
++# if defined(PG_compound)
++ EFRM_ASSERT(PageCompound(pg) == EFRM_MMAP_USE_COMPOUND);
++# endif
++
++ /* Bug 5450: Some kernels initialise the page count
++ * to one for pages other than the first and some
++ * leave it at zero. We allow either behaviour
++ * here, but disallow anything strange. Newer
++ * kernels only define set_page_count in an
++ * internal header file, so we have to make do with
++ * incrementing and decrementing the reference
++ * count. Fortunately, those kernels don't set the
++ * reference count to one on all the pages. */
++ pg_count = atomic_read(&page_count_field(pg));
++# if EFRM_MMAP_RESET_REFCNT
++ if (pg_count != pg_count_zero)
++ EFRM_ASSERT(pg_count == pg_count_zero + 1);
++# else
++ EFRM_ASSERT(pg_count == pg_count_zero);
++# endif
++ }
++ }
++#endif
++
++ /* Split the multi-page allocation if necessary. */
++#if EFRM_MMAP_USE_SPLIT
++ for (pg = start_pg; pg < end_pg; pg++) {
++
++ /* This is no longer a compound page. */
++# if EFRM_MMAP_USE_COMPOUND
++ ClearPageCompound(pg);
++ EFRM_ASSERT(PageCompound(pg) == 0);
++# endif
++
++# ifndef NDEBUG
++ {
++ int pg_count = page_count(pg);
++ /* Bug 5450: The page count can be zero or one here. */
++ if (pg == start_pg) {
++ EFRM_ASSERT(pg_count == 1);
++ } else {
++# if EFRM_MMAP_RESET_REFCNT
++ if (pg_count != 0)
++ EFRM_ASSERT(pg_count == 1);
++# else
++ EFRM_ASSERT(pg_count == 0);
++# endif
++ }
++ }
++# endif
++
++ /* Get a reference which will be released after the pages have
++ * been passed back to pci_free_consistent. */
++# if EFRM_MMAP_RESET_REFCNT
++ /* Bug 5450: Reset the reference count since the count might
++ * already be 1. */
++ ci_set_page_count(pg, (pg == start_pg) ? 2 : 1);
++# else
++ get_page(pg);
++# endif
++ }
++#endif
++
++ /* Fudge the reference count if necessary. */
++#if EFRM_MMAP_USE_INCREMENT
++ for (pg = start_pg; pg < end_pg; pg++)
++ inc_page_count(pg);
++#endif
++}
++
++static inline void pci_mmap_pages_hack_before_free(caddr_t kva, unsigned order)
++{
++#if EFRM_MMAP_USE_INCREMENT || !defined(NDEBUG)
++ /* Drop the references taken in pci_mmap_pages_hack_after_alloc */
++ unsigned pfn = __pa(kva) >> PAGE_SHIFT;
++ struct page *start_pg = pfn_to_page(pfn);
++ struct page *end_pg = start_pg + (1 << order);
++ struct page *pg;
++
++ /* Compound pages don't get created for order 0 pages and there's no
++ * fixing up needs to be done. */
++ if (order == 0)
++ return;
++
++ if (PageReserved(start_pg))
++ return;
++
++# if EFRM_MMAP_USE_INCREMENT
++ for (pg = start_pg; pg < end_pg; pg++)
++ dec_page_count(pg);
++# endif
++
++#if !defined(NDEBUG)
++ EFRM_ASSERT(page_count(start_pg) == 1+EFRM_MMAP_USE_SPLIT);
++
++# if EFRM_MMAP_USE_COMPOUND && !EFRM_MMAP_USE_SPLIT
++ for (pg = start_pg; pg < end_pg; pg++)
++ EFRM_ASSERT(PageCompound(pg));
++# else
++ for (pg = start_pg+1; pg < end_pg; pg++) {
++ unsigned exp_pg_count = EFRM_MMAP_USE_SPLIT;
++ /* NB. If this assertion fires, either we've messed up the
++ * page counting or someone is holding on to a reference.
++ */
++ EFRM_ASSERT(page_count(pg) == exp_pg_count);
++ }
++# endif
++#endif
++
++#endif
++}
++
++static inline void pci_mmap_pages_hack_after_free(caddr_t kva, unsigned order)
++{
++#if EFRM_MMAP_USE_SPLIT
++ /* Drop the references taken in pci_mmap_pages_hack_after_alloc */
++ unsigned pfn = __pa(kva) >> PAGE_SHIFT;
++ struct page *start_pg = pfn_to_page(pfn);
++ struct page *end_pg = start_pg + (1 << order);
++ struct page *pg;
++
++ /* Compound pages don't get created for order 0 pages and there's no
++ * fixing up needs to be done. */
++ if (order == 0)
++ return;
++
++ if (PageReserved(start_pg))
++ return;
++
++ for (pg = start_pg; pg < end_pg; pg++) {
++ EFRM_ASSERT(page_count(pg) == 1);
++ put_page(pg);
++ }
++#endif
++}
++
++
++#if EFRM_IOPAGE_COUNTS_ENABLED
++
++static int iopage_counts[8];
++
++void dump_iopage_counts(void)
++{
++ EFRM_NOTICE("iopage counts: %d %d %d %d %d %d %d %d", iopage_counts[0],
++ iopage_counts[1], iopage_counts[2], iopage_counts[3],
++ iopage_counts[4], iopage_counts[5], iopage_counts[6],
++ iopage_counts[7]);
++}
++
++#endif
++
++
++
++/*********** pci_alloc_consistent / pci_free_consistent ***********/
++
++void *efrm_dma_alloc_coherent(struct device *dev, size_t size,
++ dma_addr_t *dma_addr, int flag)
++{
++ struct pci_dev *pci_dev;
++ void *ptr;
++ unsigned order;
++ EFRM_IOMMU_DECL;
++
++ order = __ffs(size/PAGE_SIZE);
++ EFRM_ASSERT(size == (PAGE_SIZE<<order));
++
++ /* NB. The caller may well set __GFP_COMP. However we can't
++ * rely on this working on older kernels. 2.6.9 only acts on
++ * __GFP_COMP if CONFIG_HUGETLB_PAGE is defined. If the flag
++ * did have an effect then PG_compound will be set on the
++ * pages. */
++
++ if (use_pci_alloc) {
++ /* Can't take a spinlock here since the allocation can
++ * block. */
++ ptr = dma_alloc_coherent(dev, size, dma_addr, flag);
++ if (ptr == NULL)
++ return ptr;
++ } else {
++#ifdef CONFIG_SWIOTLB /* BUG1340 */
++ if (swiotlb) {
++ EFRM_ERR("%s: This kernel is using DMA bounce "
++ "buffers. Please upgrade kernel to "
++ "linux2.6 or reduce the amount of RAM "
++ "with mem=XXX.", __FUNCTION__);
++ return NULL;
++ }
++#endif
++ ptr = (void *)__get_free_pages(flag, order);
++
++ if (ptr == NULL)
++ return NULL;
++
++ EFRM_IOMMU_LOCK();
++ pci_dev = container_of(dev, struct pci_dev, dev);
++ *dma_addr = pci_map_single(pci_dev, ptr, size,
++ PCI_DMA_BIDIRECTIONAL);
++ EFRM_IOMMU_UNLOCK();
++ if (pci_dma_mapping_error(*dma_addr)) {
++ free_pages((unsigned long)ptr, order);
++ return NULL;
++ }
++ }
++
++#ifndef CONFIG_IA64
++ pci_mmap_pages_hack_after_alloc(ptr, order);
++#endif
++
++#if EFRM_IOPAGE_COUNTS_ENABLED
++ if (order < 8)
++ iopage_counts[order]++;
++ else
++ EFRM_ERR("Huge iopages alloc (order=%d) ??? (not counted)",
++ order);
++#endif
++
++ return ptr;
++}
++
++void efrm_dma_free_coherent(struct device *dev, size_t size,
++ void *ptr, dma_addr_t dma_addr)
++{
++ struct pci_dev *pci_dev;
++ unsigned order;
++ EFRM_IOMMU_DECL;
++
++ order = __ffs(size/PAGE_SIZE);
++ EFRM_ASSERT(size == (PAGE_SIZE<<order));
++
++#if EFRM_IOPAGE_COUNTS_ENABLED
++ if (order < 8)
++ --iopage_counts[order];
++ else
++ EFRM_ERR("Huge iopages free (order=%d) ??? (not counted)",
++ order);
++#endif
++#ifndef CONFIG_IA64
++ pci_mmap_pages_hack_before_free(ptr, order);
++#endif
++ if (use_pci_alloc) {
++ EFRM_IOMMU_LOCK();
++ dma_free_coherent(dev, size, ptr, dma_addr);
++ EFRM_IOMMU_UNLOCK();
++ } else {
++ pci_dev = container_of(dev, struct pci_dev, dev);
++ EFRM_IOMMU_LOCK();
++ efrm_pci_unmap_single(pci_dev, dma_addr, size,
++ PCI_DMA_BIDIRECTIONAL);
++ EFRM_IOMMU_UNLOCK();
++
++ free_pages((unsigned long)ptr, order);
++ }
++
++#ifndef CONFIG_IA64
++ pci_mmap_pages_hack_after_free(ptr, order);
++#endif
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/kernel_compat.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/kernel_compat.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/kernel_compat.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/kernel_compat.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,239 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides compatibility layer for various Linux kernel versions
++ * (starting from 2.6.9 RHEL kernel).
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H
++#define DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H
++
++#include <linux/version.h>
++
++/********* wait_for_completion_timeout() ********************/
++#include <linux/sched.h>
++
++/* RHEL_RELEASE_CODE from linux/version.h is only defined for 2.6.9-55EL
++ * UTS_RELEASE is unfortunately unusable
++ * Really only need this fix for <2.6.9-34EL
++ */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) && \
++ !defined(RHEL_RELEASE_CODE)
++
++static inline unsigned long fastcall __sched
++efrm_wait_for_completion_timeout(struct completion *x, unsigned long timeout)
++{
++ might_sleep();
++
++ spin_lock_irq(&x->wait.lock);
++ if (!x->done) {
++ DECLARE_WAITQUEUE(wait, current);
++
++ wait.flags |= WQ_FLAG_EXCLUSIVE;
++ __add_wait_queue_tail(&x->wait, &wait);
++ do {
++ __set_current_state(TASK_UNINTERRUPTIBLE);
++ spin_unlock_irq(&x->wait.lock);
++ timeout = schedule_timeout(timeout);
++ spin_lock_irq(&x->wait.lock);
++ if (!timeout) {
++ __remove_wait_queue(&x->wait, &wait);
++ goto out;
++ }
++ } while (!x->done);
++ __remove_wait_queue(&x->wait, &wait);
++ }
++ x->done--;
++out:
++ spin_unlock_irq(&x->wait.lock);
++ return timeout;
++}
++
++# ifdef wait_for_completion_timeout
++# undef wait_for_completion_timeout
++# endif
++# define wait_for_completion_timeout efrm_wait_for_completion_timeout
++
++#endif
++
++/********* pci_map_*() ********************/
++
++#include <linux/pci.h>
++
++/* Bug 4560: Some kernels leak IOMMU entries under heavy load. Use a
++ * spinlock to serialise access where possible to alleviate the
++ * problem.
++ *
++ * NB. This is duplicated in the net driver. Please keep in sync. */
++#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && \
++ (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)) && \
++ defined(__x86_64__) && defined(CONFIG_SMP))
++
++#define EFRM_HAVE_IOMMU_LOCK 1
++
++#if ((LINUX_VERSION_CODE == KERNEL_VERSION(2,6,5)) && \
++ defined(CONFIG_SUSE_KERNEL))
++#define EFRM_NEED_ALTERNATE_MAX_PFN 1
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
++#if defined(CONFIG_GART_IOMMU)
++#define EFRM_NO_IOMMU no_iommu
++#else
++#define EFRM_NO_IOMMU 1
++#endif
++#else
++#define EFRM_NO_IOMMU 0
++#endif
++
++/* Set to 0 if we should never use the lock. Set to 1 if we should
++ * automatically determine if we should use the lock. Set to 2 if we
++ * should always use the lock. */
++extern unsigned int efx_use_iommu_lock;
++/* Defined in the net driver. */
++extern spinlock_t efx_iommu_lock;
++/* Non-zero if there is a card which needs the lock. */
++extern int efrm_need_iommu_lock;
++
++/* The IRQ state is needed if the lock is being used. The flag is
++ * cached to ensure that every lock is followed by an unlock, even
++ * if the global flag changes in the middle of the operation. */
++
++#define EFRM_IOMMU_DECL \
++ unsigned long efx_iommu_irq_state = 0; \
++ int efx_iommu_using_lock;
++#define EFRM_IOMMU_LOCK() \
++ do { \
++ efx_iommu_using_lock = (efx_use_iommu_lock && \
++ (efrm_need_iommu_lock || \
++ efx_use_iommu_lock >= 2)); \
++ if (efx_iommu_using_lock) \
++ spin_lock_irqsave(&efx_iommu_lock, efx_iommu_irq_state);\
++ } while (0)
++#define EFRM_IOMMU_UNLOCK() \
++ do { \
++ if (efx_iommu_using_lock) \
++ spin_unlock_irqrestore(&efx_iommu_lock, \
++ efx_iommu_irq_state); \
++ } while (0)
++
++#else /* defined(__x86_64__) && defined(CONFIG_SMP) */
++
++#define EFRM_HAVE_IOMMU_LOCK 0
++#define EFRM_IOMMU_DECL
++#define EFRM_IOMMU_LOCK() do {} while (0)
++#define EFRM_IOMMU_UNLOCK() do {} while (0)
++
++#endif
++
++static inline dma_addr_t efrm_pci_map_single(struct pci_dev *hwdev, void *ptr,
++ size_t size, int direction)
++{
++ dma_addr_t dma_addr;
++ EFRM_IOMMU_DECL;
++
++ EFRM_IOMMU_LOCK();
++ dma_addr = pci_map_single(hwdev, ptr, size, direction);
++ EFRM_IOMMU_UNLOCK();
++
++ return dma_addr;
++}
++
++static inline void efrm_pci_unmap_single(struct pci_dev *hwdev,
++ dma_addr_t dma_addr, size_t size,
++ int direction)
++{
++ EFRM_IOMMU_DECL;
++
++ EFRM_IOMMU_LOCK();
++ pci_unmap_single(hwdev, dma_addr, size, direction);
++ EFRM_IOMMU_UNLOCK();
++}
++
++static inline dma_addr_t efrm_pci_map_page(struct pci_dev *hwdev,
++ struct page *page,
++ unsigned long offset, size_t size,
++ int direction)
++{
++ dma_addr_t dma_addr;
++ EFRM_IOMMU_DECL;
++
++ EFRM_IOMMU_LOCK();
++ dma_addr = pci_map_page(hwdev, page, offset, size, direction);
++ EFRM_IOMMU_UNLOCK();
++
++ return dma_addr;
++}
++
++static inline void efrm_pci_unmap_page(struct pci_dev *hwdev,
++ dma_addr_t dma_addr, size_t size,
++ int direction)
++{
++ EFRM_IOMMU_DECL;
++
++ EFRM_IOMMU_LOCK();
++ pci_unmap_page(hwdev, dma_addr, size, direction);
++ EFRM_IOMMU_UNLOCK();
++}
++
++#ifndef IN_KERNEL_COMPAT_C
++# ifndef __GFP_COMP
++# define __GFP_COMP 0
++# endif
++# ifndef __GFP_ZERO
++# define __GFP_ZERO 0
++# endif
++#endif
++
++extern void *efrm_dma_alloc_coherent(struct device *dev, size_t size,
++ dma_addr_t *dma_addr, int flag);
++
++extern void efrm_dma_free_coherent(struct device *dev, size_t size,
++ void *ptr, dma_addr_t dma_addr);
++
++static inline void *efrm_pci_alloc_consistent(struct pci_dev *hwdev,
++ size_t size,
++ dma_addr_t *dma_addr)
++{
++ return efrm_dma_alloc_coherent(&hwdev->dev, size, dma_addr,
++ GFP_ATOMIC);
++}
++
++static inline void efrm_pci_free_consistent(struct pci_dev *hwdev, size_t size,
++ void *ptr, dma_addr_t dma_addr)
++{
++ efrm_dma_free_coherent(&hwdev->dev, size, ptr, dma_addr);
++}
++
++#endif /* DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/kernel_proc.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/kernel_proc.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/kernel_proc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/kernel_proc.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,111 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains /proc/driver/sfc_resource/ implementation.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/debug.h>
++#include <ci/efrm/nic_table.h>
++#include <ci/efrm/driver_private.h>
++#include <linux/proc_fs.h>
++
++/** Top level directory for sfc specific stats **/
++static struct proc_dir_entry *efrm_proc_root; /* = NULL */
++
++static int
++efrm_resource_read_proc(char *buf, char **start, off_t offset, int count,
++ int *eof, void *data);
++
++int efrm_install_proc_entries(void)
++{
++ /* create the top-level directory for etherfabric specific stuff */
++ efrm_proc_root = proc_mkdir("sfc_resource", proc_root_driver);
++ if (!efrm_proc_root)
++ return -ENOMEM;
++ EFRM_ASSERT(efrm_proc_root);
++
++ if (create_proc_read_entry("resources", 0, efrm_proc_root,
++ efrm_resource_read_proc, 0) == NULL) {
++ EFRM_WARN("%s: Unable to create /proc/drivers/sfc_resource/"
++ "resources", __FUNCTION__);
++ }
++ return 0;
++}
++
++void efrm_uninstall_proc_entries(void)
++{
++ EFRM_ASSERT(efrm_proc_root);
++ remove_proc_entry("resources", efrm_proc_root);
++ remove_proc_entry("sfc_resource", proc_root_driver);
++ efrm_proc_root = NULL;
++}
++
++/****************************************************************************
++ *
++ * /proc/drivers/sfc/resources
++ *
++ ****************************************************************************/
++
++#define EFRM_PROC_PRINTF(buf, len, fmt, ...) \
++ do { \
++ if (count - len > 0) \
++ len += snprintf(buf+len, count-len, (fmt), \
++ __VA_ARGS__); \
++ } while (0)
++
++static int
++efrm_resource_read_proc(char *buf, char **start, off_t offset, int count,
++ int *eof, void *data)
++{
++ irq_flags_t lock_flags;
++ int len = 0;
++ int type;
++ struct efrm_resource_manager *rm;
++
++ for (type = 0; type < EFRM_RESOURCE_NUM; type++) {
++ rm = efrm_rm_table[type];
++ if (rm == NULL)
++ continue;
++
++ EFRM_PROC_PRINTF(buf, len, "*** %s ***\n", rm->rm_name);
++
++ spin_lock_irqsave(&rm->rm_lock, lock_flags);
++ EFRM_PROC_PRINTF(buf, len, "current = %u\n", rm->rm_resources);
++ EFRM_PROC_PRINTF(buf, len, " max = %u\n\n",
++ rm->rm_resources_hiwat);
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++ }
++
++ return count ? strlen(buf) : 0;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/kfifo.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/kfifo.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/kfifo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/kfifo.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,212 @@
++/*
++ * A simple kernel FIFO implementation.
++ *
++ * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
++ *
++ * 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; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ * This file is stolen from the Linux kernel sources
++ * (linux-2.6.22/kernel/kfifo.c) into sfc_resource driver.
++ * It should be used for old kernels without kfifo implementation.
++ * Most part of linux/kfifo.h is incorporated into
++ * ci/efrm/sysdep_linux.h.
++ */
++#include <ci/efrm/sysdep_linux.h>
++#ifdef HAS_NO_KFIFO
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++/*#include <linux/kfifo.h>*/
++
++/**
++ * kfifo_init - allocates a new FIFO using a preallocated buffer
++ * @buffer: the preallocated buffer to be used.
++ * @size: the size of the internal buffer, this have to be a power of 2.
++ * @gfp_mask: get_free_pages mask, passed to kmalloc()
++ * @lock: the lock to be used to protect the fifo buffer
++ *
++ * Do NOT pass the kfifo to kfifo_free() after use! Simply free the
++ * &struct kfifo with kfree().
++ */
++struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
++ gfp_t gfp_mask, spinlock_t * lock)
++{
++ struct kfifo *fifo;
++
++ /* size must be a power of 2 */
++ BUG_ON(size & (size - 1));
++
++ fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
++ if (!fifo)
++ return ERR_PTR(-ENOMEM);
++
++ fifo->buffer = buffer;
++ fifo->size = size;
++ fifo->in = fifo->out = 0;
++ fifo->lock = lock;
++
++ return fifo;
++}
++
++EXPORT_SYMBOL(kfifo_init);
++
++/**
++ * kfifo_alloc - allocates a new FIFO and its internal buffer
++ * @size: the size of the internal buffer to be allocated.
++ * @gfp_mask: get_free_pages mask, passed to kmalloc()
++ * @lock: the lock to be used to protect the fifo buffer
++ *
++ * The size will be rounded-up to a power of 2.
++ */
++struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t * lock)
++{
++ unsigned char *buffer;
++ struct kfifo *ret;
++
++ /*
++ * round up to the next power of 2, since our 'let the indices
++ * wrap' tachnique works only in this case.
++ */
++ if (size & (size - 1)) {
++ BUG_ON(size > 0x80000000);
++ size = roundup_pow_of_two(size);
++ }
++
++ buffer = kmalloc(size, gfp_mask);
++ if (!buffer)
++ return ERR_PTR(-ENOMEM);
++
++ ret = kfifo_init(buffer, size, gfp_mask, lock);
++
++ if (IS_ERR(ret))
++ kfree(buffer);
++
++ return ret;
++}
++
++EXPORT_SYMBOL(kfifo_alloc);
++
++/**
++ * kfifo_free - frees the FIFO
++ * @fifo: the fifo to be freed.
++ */
++void kfifo_free(struct kfifo *fifo)
++{
++ kfree(fifo->buffer);
++ kfree(fifo);
++}
++
++EXPORT_SYMBOL(kfifo_free);
++
++/**
++ * __kfifo_put - puts some data into the FIFO, no locking version
++ * @fifo: the fifo to be used.
++ * @buffer: the data to be added.
++ * @len: the length of the data to be added.
++ *
++ * This function copies at most @len bytes from the @buffer into
++ * the FIFO depending on the free space, and returns the number of
++ * bytes copied.
++ *
++ * Note that with only one concurrent reader and one concurrent
++ * writer, you don't need extra locking to use these functions.
++ */
++unsigned int
++__kfifo_put(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
++{
++ unsigned int l;
++
++ len = min(len, fifo->size - fifo->in + fifo->out);
++
++ /*
++ * Ensure that we sample the fifo->out index -before- we
++ * start putting bytes into the kfifo.
++ */
++
++ smp_mb();
++
++ /* first put the data starting from fifo->in to buffer end */
++ l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
++ memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
++
++ /* then put the rest (if any) at the beginning of the buffer */
++ memcpy(fifo->buffer, buffer + l, len - l);
++
++ /*
++ * Ensure that we add the bytes to the kfifo -before-
++ * we update the fifo->in index.
++ */
++
++ smp_wmb();
++
++ fifo->in += len;
++
++ return len;
++}
++
++EXPORT_SYMBOL(__kfifo_put);
++
++/**
++ * __kfifo_get - gets some data from the FIFO, no locking version
++ * @fifo: the fifo to be used.
++ * @buffer: where the data must be copied.
++ * @len: the size of the destination buffer.
++ *
++ * This function copies at most @len bytes from the FIFO into the
++ * @buffer and returns the number of copied bytes.
++ *
++ * Note that with only one concurrent reader and one concurrent
++ * writer, you don't need extra locking to use these functions.
++ */
++unsigned int
++__kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
++{
++ unsigned int l;
++
++ len = min(len, fifo->in - fifo->out);
++
++ /*
++ * Ensure that we sample the fifo->in index -before- we
++ * start removing bytes from the kfifo.
++ */
++
++ smp_rmb();
++
++ /* first get the data from fifo->out until the end of the buffer */
++ l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
++ memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
++
++ /* then get the rest (if any) from the beginning of the buffer */
++ memcpy(buffer + l, fifo->buffer, len - l);
++
++ /*
++ * Ensure that we remove the bytes from the kfifo -before-
++ * we update the fifo->out index.
++ */
++
++ smp_mb();
++
++ fifo->out += len;
++
++ return len;
++}
++
++EXPORT_SYMBOL(__kfifo_get);
++#endif
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/linux_resource_internal.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/linux_resource_internal.h
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/linux_resource_internal.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/linux_resource_internal.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,75 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains Linux-specific API internal for the resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __LINUX_RESOURCE_INTERNAL__
++#define __LINUX_RESOURCE_INTERNAL__
++
++#include <ci/driver/resource/linux_efhw_nic.h>
++#include <ci/efrm/debug.h>
++#include <ci/efrm/driver_private.h>
++#include <ci/driver/efab/hardware.h>
++
++
++/*! Linux specific EtherFabric initialisation */
++extern int
++linux_efrm_nic_ctor(struct linux_efhw_nic *, struct pci_dev *,
++ spinlock_t *reg_lock,
++ unsigned nic_flags, unsigned nic_options);
++
++/*! Linux specific EtherFabric initialisation */
++extern void linux_efrm_nic_dtor(struct linux_efhw_nic *);
++
++/*! Linux specific EtherFabric initialisation -- interrupt registration */
++extern int linux_efrm_irq_ctor(struct linux_efhw_nic *);
++
++/*! Linux specific EtherFabric initialisation -- interrupt deregistration */
++extern void linux_efrm_irq_dtor(struct linux_efhw_nic *);
++
++extern int efrm_driverlink_register(void);
++extern void efrm_driverlink_unregister(void);
++
++extern int
++efrm_nic_add(struct pci_dev *dev, unsigned int opts, const uint8_t *mac_addr,
++ struct linux_efhw_nic **lnic_out, spinlock_t *reg_lock,
++ int bt_min, int bt_max, const struct vi_resource_dimensions *);
++extern void efrm_nic_del(struct linux_efhw_nic *);
++
++
++extern int efrm_install_proc_entries(void);
++extern void efrm_uninstall_proc_entries(void);
++
++#endif /* __LINUX_RESOURCE_INTERNAL__ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/Makefile linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/Makefile
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,15 @@
++obj-$(CONFIG_SFC_RESOURCE) := sfc_resource.o
++
++EXTRA_CFLAGS += -D__CI_HARDWARE_CONFIG_FALCON__
++EXTRA_CFLAGS += -D__ci_driver__
++EXTRA_CFLAGS += -Werror
++EXTRA_CFLAGS += -Idrivers/net/sfc -Idrivers/net/sfc/sfc_resource
++
++sfc_resource-objs := resource_driver.o iopage.o efx_vi_shm.o \
++ driverlink_new.o kernel_proc.o kfifo.o \
++ nic.o eventq.o falcon.o falcon_mac.o falcon_hash.o \
++ assert_valid.o buddy.o buffer_table.o filter_resource.o \
++ iobufset_resource.o resource_manager.o resources.o \
++ vi_resource_alloc.o vi_resource_event.o vi_resource_flush.o \
++ vi_resource_manager.o driver_object.o kernel_compat.o
++
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/nic.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/nic.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/nic.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/nic.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,190 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains EtherFabric Generic NIC instance (init, interrupts,
++ * etc)
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efhw/debug.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efhw/falcon.h>
++#include <ci/efhw/nic.h>
++#include <ci/efhw/eventq.h>
++
++
++int efhw_device_type_init(struct efhw_device_type *dt,
++ int vendor_id, int device_id,
++ int class_revision)
++{
++ if (vendor_id != 0x1924)
++ return 0;
++
++ switch (device_id) {
++ case 0x0703:
++ case 0x6703:
++ dt->arch = EFHW_ARCH_FALCON;
++ dt->variant = 'A';
++ switch (class_revision) {
++ case 0:
++ dt->revision = 0;
++ break;
++ case 1:
++ dt->revision = 1;
++ break;
++ default:
++ return 0;
++ }
++ break;
++ case 0x0710:
++ dt->arch = EFHW_ARCH_FALCON;
++ dt->variant = 'B';
++ switch (class_revision) {
++ case 2:
++ dt->revision = 0;
++ break;
++ default:
++ return 0;
++ }
++ break;
++ default:
++ return 0;
++ }
++
++ return 1;
++}
++
++
++/*--------------------------------------------------------------------
++ *
++ * NIC Initialisation
++ *
++ *--------------------------------------------------------------------*/
++
++/* make this separate from initialising data structure
++** to allow this to be called at a later time once we can access PCI
++** config space to find out what hardware we have
++*/
++void efhw_nic_init(struct efhw_nic *nic, unsigned flags, unsigned options,
++ struct efhw_device_type dev_type)
++{
++ int i;
++
++ nic->devtype = dev_type;
++ nic->flags = flags;
++ nic->options = options;
++ nic->bar_ioaddr = 0;
++ spin_lock_init(&nic->the_reg_lock);
++ nic->reg_lock = &nic->the_reg_lock;
++ nic->mtu = 1500 + ETH_HLEN;
++
++ for (i = 0; i < EFHW_KEVENTQ_MAX; i++)
++ nic->irq_unit[i] = EFHW_IRQ_UNIT_UNUSED;
++
++ switch (nic->devtype.arch) {
++ case EFHW_ARCH_FALCON:
++ nic->evq_sizes = 512 | 1024 | 2048 | 4096 | 8192 |
++ 16384 | 32768;
++ nic->txq_sizes = 512 | 1024 | 2048 | 4096;
++ nic->rxq_sizes = 512 | 1024 | 2048 | 4096;
++ nic->efhw_func = &falcon_char_functional_units;
++ nic->ctr_ap_bytes = EFHW_64M;
++ switch (nic->devtype.variant) {
++ case 'A':
++ nic->ctr_ap_bar = FALCON_S_CTR_AP_BAR;
++ break;
++ case 'B':
++ nic->flags |= NIC_FLAG_NO_INTERRUPT;
++ nic->ctr_ap_bar = FALCON_P_CTR_AP_BAR;
++ break;
++ default:
++ EFHW_ASSERT(0);
++ break;
++ }
++ break;
++ default:
++ EFHW_ASSERT(0);
++ break;
++ }
++}
++
++
++void efhw_nic_close_interrupts(struct efhw_nic *nic)
++{
++ int i;
++
++ EFHW_ASSERT(nic);
++ if (!efhw_nic_have_hw(nic))
++ return;
++
++ EFHW_ASSERT(efhw_nic_have_hw(nic));
++
++ for (i = 0; i < EFHW_KEVENTQ_MAX; i++) {
++ if (nic->irq_unit[i] != EFHW_IRQ_UNIT_UNUSED)
++ efhw_nic_interrupt_disable(nic, i);
++ }
++}
++
++void efhw_nic_dtor(struct efhw_nic *nic)
++{
++ EFHW_ASSERT(nic);
++
++ /* Check that we have functional units because the software only
++ * driver doesn't initialise anything hardware related any more */
++
++#ifndef __ci_ul_driver__
++ /* close interrupts is called first because the act of deregistering
++ the driver could cause this driver to change from master to slave
++ and hence the implicit interrupt mappings would be wrong */
++
++ EFHW_TRACE("%s: functional units ... ", __FUNCTION__);
++
++ if (efhw_nic_have_functional_units(nic)) {
++ efhw_nic_close_interrupts(nic);
++ efhw_nic_close_hardware(nic);
++ }
++ EFHW_TRACE("%s: functional units ... done", __FUNCTION__);
++#endif
++
++ /* destroy event queues */
++ EFHW_TRACE("%s: event queues ... ", __FUNCTION__);
++
++#ifndef __ci_ul_driver__
++ {
++ int i;
++ for (i = 0; i < EFHW_KEVENTQ_MAX; ++i)
++ if (nic->evq[i].evq_mask)
++ efhw_keventq_dtor(nic, &nic->evq[i]);
++ }
++#endif
++
++ EFHW_TRACE("%s: event queues ... done", __FUNCTION__);
++
++ spin_lock_destroy(&nic->the_reg_lock);
++
++ EFHW_TRACE("%s: DONE", __FUNCTION__);
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/resource_driver.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/resource_driver.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/resource_driver.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/resource_driver.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,640 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains main driver entry points.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "linux_resource_internal.h"
++#include "kernel_compat.h"
++#include <ci/efrm/nic_table.h>
++#include <ci/driver/resource/efx_vi.h>
++#include <ci/efhw/eventq.h>
++#include <ci/efhw/nic.h>
++#include <ci/efrm/buffer_table.h>
++#include <ci/efrm/vi_resource_private.h>
++#include <ci/efrm/driver_private.h>
++
++#if EFRM_HAVE_IOMMU_LOCK
++#ifdef EFRM_NEED_ALTERNATE_MAX_PFN
++extern unsigned long blk_max_pfn;
++#define max_pfn blk_max_pfn
++#else
++#include <linux/bootmem.h>
++#endif
++#endif
++
++MODULE_AUTHOR("Solarflare Communications");
++MODULE_LICENSE("GPL");
++
++static struct efhw_ev_handler ev_handler = {
++ .wakeup_fn = efrm_handle_wakeup_event,
++ .timeout_fn = efrm_handle_timeout_event,
++ .dmaq_flushed_fn = efrm_handle_dmaq_flushed,
++};
++
++#if EFRM_HAVE_IOMMU_LOCK
++int efrm_need_iommu_lock;
++EXPORT_SYMBOL(efrm_need_iommu_lock);
++#endif
++
++const int max_hardware_init_repeats = 10;
++
++/*--------------------------------------------------------------------
++ *
++ * Module load time variables
++ *
++ *--------------------------------------------------------------------*/
++/* See docs/notes/pci_alloc_consistent */
++int use_pci_alloc = 1; /* Use pci_alloc_consistent to alloc iopages */
++static int do_irq = 1; /* enable interrupts */
++
++#if defined(CONFIG_X86_XEN)
++static int irq_moderation = 60; /* interrupt moderation (60 usec) */
++#else
++static int irq_moderation = 20; /* interrupt moderation (20 usec) */
++#endif
++static int nic_options = NIC_OPT_DEFAULT;
++int efx_vi_eventq_size = EFX_VI_EVENTQ_SIZE_DEFAULT;
++
++module_param(do_irq, int, S_IRUGO);
++MODULE_PARM_DESC(do_irq, "Enable interrupts. "
++ "Do not turn it off unless you know what are you doing.");
++module_param(irq_moderation, int, S_IRUGO);
++MODULE_PARM_DESC(irq_moderation, "IRQ moderation in usec");
++module_param(nic_options, int, S_IRUGO);
++MODULE_PARM_DESC(nic_options, "Nic options -- see efhw_types.h");
++module_param(use_pci_alloc, int, S_IRUGO);
++MODULE_PARM_DESC(use_pci_alloc, "Use pci_alloc_consistent to alloc iopages "
++ "(autodetected by kernel version)");
++module_param(efx_vi_eventq_size, int, S_IRUGO);
++MODULE_PARM_DESC(efx_vi_eventq_size,
++ "Size of event queue allocated by efx_vi library");
++
++/*--------------------------------------------------------------------
++ *
++ * Linux specific NIC initialisation
++ *
++ *--------------------------------------------------------------------*/
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++# define IRQ_PT_REGS_ARG , struct pt_regs *regs __attribute__ ((unused))
++#else
++# define IRQ_PT_REGS_ARG
++#endif
++
++#ifndef IRQF_SHARED
++# define IRQF_SHARED SA_SHIRQ
++#endif
++
++static inline irqreturn_t
++linux_efrm_interrupt(int irr, void *dev_id IRQ_PT_REGS_ARG)
++{
++ return efhw_nic_interrupt((struct efhw_nic *)dev_id);
++}
++
++int linux_efrm_irq_ctor(struct linux_efhw_nic *lnic)
++{
++ struct efhw_nic *nic = &lnic->nic;
++
++ nic->flags &= ~NIC_FLAG_MSI;
++ if (nic->flags & NIC_FLAG_TRY_MSI) {
++ int rc = pci_enable_msi(lnic->pci_dev);
++ if (rc < 0) {
++ EFRM_WARN("%s: Could not enable MSI (%d)",
++ __FUNCTION__, rc);
++ EFRM_WARN("%s: Continuing with legacy interrupt mode",
++ __FUNCTION__);
++ } else {
++ EFRM_NOTICE("%s: MSI enabled", __FUNCTION__);
++ nic->flags |= NIC_FLAG_MSI;
++ }
++ }
++
++ if (request_irq(lnic->pci_dev->irq, linux_efrm_interrupt,
++ IRQF_SHARED, "sfc_resource", nic)) {
++ EFRM_ERR("Request for interrupt #%d failed",
++ lnic->pci_dev->irq);
++ nic->flags &= ~NIC_FLAG_OS_IRQ_EN;
++ return -EBUSY;
++ }
++ nic->flags |= NIC_FLAG_OS_IRQ_EN;
++
++ return 0;
++}
++
++void linux_efrm_irq_dtor(struct linux_efhw_nic *lnic)
++{
++ EFRM_TRACE("linux_efrm_irq_dtor: start");
++
++ if (lnic->nic.flags & NIC_FLAG_OS_IRQ_EN) {
++ free_irq(lnic->pci_dev->irq, &lnic->nic);
++ lnic->nic.flags &= ~NIC_FLAG_OS_IRQ_EN;
++ }
++
++ if (lnic->nic.flags & NIC_FLAG_MSI) {
++ pci_disable_msi(lnic->pci_dev);
++ lnic->nic.flags &= ~NIC_FLAG_MSI;
++ }
++
++ EFRM_TRACE("linux_efrm_irq_dtor: done");
++}
++
++/* Allocate buffer table entries for a particular NIC.
++ */
++static int efrm_nic_buffer_table_alloc(struct efhw_nic *nic)
++{
++ int capacity;
++ int page_order;
++ int i;
++ int rc;
++
++ /* Choose queue size. */
++ for (capacity = 8192; capacity <= nic->evq_sizes; capacity <<= 1) {
++ if (capacity > nic->evq_sizes) {
++ EFRM_ERR
++ ("%s: Unable to choose EVQ size (supported=%x)",
++ __FUNCTION__, nic->evq_sizes);
++ return -E2BIG;
++ } else if (capacity & nic->evq_sizes)
++ break;
++ }
++ for (i = 0; i < EFHW_KEVENTQ_MAX; ++i) {
++ nic->evq[i].hw.capacity = capacity;
++ nic->evq[i].hw.buf_tbl_alloc.base = (unsigned)-1;
++ }
++
++ /* allocate buffer table entries to map onto the iobuffer */
++ page_order = get_order(capacity * sizeof(efhw_event_t));
++ if (!(nic->flags & NIC_FLAG_NO_INTERRUPT)) {
++ rc = efrm_buffer_table_alloc(page_order,
++ &nic->evq[0].hw.buf_tbl_alloc);
++ if (rc < 0) {
++ EFRM_WARN
++ ("%s: failed (%d) to alloc %d buffer table entries",
++ __FUNCTION__, rc, page_order);
++ return rc;
++ }
++ }
++ rc = efrm_buffer_table_alloc(page_order,
++ &nic->evq[FALCON_EVQ_NONIRQ].hw.
++ buf_tbl_alloc);
++ if (rc < 0) {
++ EFRM_WARN
++ ("%s: failed (%d) to alloc %d buffer table entries",
++ __FUNCTION__, rc, page_order);
++ return rc;
++ }
++
++ return 0;
++}
++
++/* Free buffer table entries allocated for a particular NIC.
++ */
++static void efrm_nic_buffer_table_free(struct efhw_nic *nic)
++{
++ int i;
++ for (i = 0; i <= FALCON_EVQ_NONIRQ; i++)
++ if (nic->evq[i].hw.buf_tbl_alloc.base != (unsigned)-1)
++ efrm_buffer_table_free(&nic->evq[i].hw.buf_tbl_alloc);
++
++}
++
++static int iomap_bar(struct linux_efhw_nic *lnic, size_t len)
++{
++ efhw_ioaddr_t ioaddr;
++
++ ioaddr = ioremap_nocache(lnic->ctr_ap_pci_addr, len);
++ if (ioaddr == 0)
++ return -ENOMEM;
++
++ lnic->nic.bar_ioaddr = ioaddr;
++ return 0;
++}
++
++static int linux_efhw_nic_map_ctr_ap(struct linux_efhw_nic *lnic)
++{
++ struct efhw_nic *nic = &lnic->nic;
++ int rc;
++
++ rc = iomap_bar(lnic, nic->ctr_ap_bytes);
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ /* Bug 5195: workaround for now. */
++ if (rc != 0 && nic->ctr_ap_bytes > 16 * 1024 * 1024) {
++ /* Try half the size for now. */
++ nic->ctr_ap_bytes /= 2;
++ EFRM_WARN("Bug 5195 WORKAROUND: retrying iomap of %d bytes",
++ nic->ctr_ap_bytes);
++ rc = iomap_bar(lnic, nic->ctr_ap_bytes);
++ }
++#endif
++
++ if (rc < 0) {
++ EFRM_ERR("Failed (%d) to map bar (%d bytes)",
++ rc, nic->ctr_ap_bytes);
++ return rc;
++ }
++
++ return rc;
++}
++
++int
++linux_efrm_nic_ctor(struct linux_efhw_nic *lnic, struct pci_dev *dev,
++ spinlock_t *reg_lock,
++ unsigned nic_flags, unsigned nic_options)
++{
++ struct efhw_device_type dev_type;
++ struct efhw_nic *nic = &lnic->nic;
++ u8 class_revision;
++ int rc;
++
++ rc = pci_read_config_byte(dev, PCI_CLASS_REVISION, &class_revision);
++ if (rc != 0) {
++ EFRM_ERR("%s: pci_read_config_byte failed (%d)",
++ __FUNCTION__, rc);
++ return rc;
++ }
++
++ if (!efhw_device_type_init(&dev_type, dev->vendor, dev->device,
++ class_revision)) {
++ EFRM_ERR("%s: efhw_device_type_init failed %04x:%04x(%d)",
++ __FUNCTION__, (unsigned) dev->vendor,
++ (unsigned) dev->device, (int) class_revision);
++ return -ENODEV;
++ }
++
++ EFRM_NOTICE("attaching device type %04x:%04x %d:%c%d",
++ (unsigned) dev->vendor, (unsigned) dev->device,
++ dev_type.arch, dev_type.variant, dev_type.revision);
++
++ /* Initialise the adapter-structure. */
++ efhw_nic_init(nic, nic_flags, nic_options, dev_type);
++ lnic->pci_dev = dev;
++
++ rc = pci_enable_device(dev);
++ if (rc < 0) {
++ EFRM_ERR("%s: pci_enable_device failed (%d)",
++ __FUNCTION__, rc);
++ return rc;
++ }
++
++ lnic->ctr_ap_pci_addr = pci_resource_start(dev, nic->ctr_ap_bar);
++
++ if (!pci_dma_supported(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) {
++ EFRM_ERR("%s: pci_dma_supported(%lx) failed", __FUNCTION__,
++ (unsigned long)EFHW_DMA_ADDRMASK);
++ return -ENODEV;
++ }
++
++ if (pci_set_dma_mask(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) {
++ EFRM_ERR("%s: pci_set_dma_mask(%lx) failed", __FUNCTION__,
++ (unsigned long)EFHW_DMA_ADDRMASK);
++ return -ENODEV;
++ }
++
++ if (pci_set_consistent_dma_mask(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) {
++ EFRM_ERR("%s: pci_set_consistent_dma_mask(%lx) failed",
++ __FUNCTION__, (unsigned long)EFHW_DMA_ADDRMASK);
++ return -ENODEV;
++ }
++
++ rc = linux_efhw_nic_map_ctr_ap(lnic);
++ if (rc < 0)
++ return rc;
++
++ /* By default struct efhw_nic contains its own lock for protecting
++ * access to nic registers. We override it with a pointer to the
++ * lock in the net driver. This is needed when resource and net
++ * drivers share a single PCI function (falcon B series).
++ */
++ nic->reg_lock = reg_lock;
++ return 0;
++}
++
++void linux_efrm_nic_dtor(struct linux_efhw_nic *lnic)
++{
++ struct efhw_nic *nic = &lnic->nic;
++ efhw_ioaddr_t bar_ioaddr = nic->bar_ioaddr;
++
++ efhw_nic_dtor(nic);
++
++ efrm_nic_buffer_table_free(nic);
++
++ /* Unmap the bar. */
++ EFRM_ASSERT(bar_ioaddr);
++ iounmap(bar_ioaddr);
++ nic->bar_ioaddr = 0;
++}
++
++/****************************************************************************
++ *
++ * efrm_tasklet - used to poll the eventq which may result in further callbacks
++ *
++ ****************************************************************************/
++
++static void efrm_tasklet(unsigned long pdev)
++{
++ struct efhw_nic *nic = (struct efhw_nic *)pdev;
++
++ EFRM_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT));
++
++ efhw_keventq_poll(nic, &nic->evq[0]);
++ EFRM_TRACE("tasklet complete");
++}
++
++/****************************************************************************
++ *
++ * char driver specific interrupt callbacks -- run at hard IRQL
++ *
++ ****************************************************************************/
++static void efrm_handle_eventq_irq(struct efhw_nic *nic, int evq)
++{
++ /* NB. The interrupt must have already been acked (for legacy mode). */
++
++ EFRM_TRACE("%s: starting tasklet", __FUNCTION__);
++ EFRM_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT));
++
++ tasklet_schedule(&linux_efhw_nic(nic)->tasklet);
++}
++
++/* A count of how many NICs this driver knows about. */
++static int n_nics_probed;
++
++/****************************************************************************
++ *
++ * efrm_nic_add: add the NIC to the resource driver
++ *
++ * NOTE: the flow of control through this routine is quite subtle
++ * because of the number of operations that can fail. We therefore
++ * take the apporaching of keeping the return code (rc) variable
++ * accurate, and only do operations while it is non-negative. Tear down
++ * is done at the end if rc is negative, depending on what has been set up
++ * by that point.
++ *
++ * So basically just make sure that any code you add checks rc>=0 before
++ * doing any work and you'll be fine.
++ *
++ ****************************************************************************/
++int
++efrm_nic_add(struct pci_dev *dev, unsigned flags, const uint8_t *mac_addr,
++ struct linux_efhw_nic **lnic_out, spinlock_t *reg_lock,
++ int bt_min, int bt_max,
++ const struct vi_resource_dimensions *res_dim)
++{
++ struct linux_efhw_nic *lnic = NULL;
++ struct efhw_nic *nic = NULL;
++ int count = 0, rc = 0, resources_init = 0;
++ int constructed = 0;
++ int registered_nic = 0;
++ int buffers_allocated = 0;
++ static unsigned nic_index; /* = 0; */
++
++ EFRM_TRACE("%s: device detected (Slot '%s', IRQ %d)", __FUNCTION__,
++ pci_name(dev) ? pci_name(dev) : "?", dev->irq);
++
++ /* Ensure that we have room for the new adapter-structure. */
++ if (efrm_nic_table.nic_count == EFHW_MAX_NR_DEVS) {
++ EFRM_WARN("%s: WARNING: too many devices", __FUNCTION__);
++ rc = -ENOMEM;
++ goto failed;
++ }
++
++ if (n_nics_probed == 0) {
++ rc = efrm_resources_init(res_dim, bt_min, bt_max);
++ if (rc != 0)
++ goto failed;
++ resources_init = 1;
++ }
++
++ /* Allocate memory for the new adapter-structure. */
++ lnic = kmalloc(sizeof(*lnic), GFP_KERNEL);
++ if (lnic == NULL) {
++ EFRM_ERR("%s: ERROR: failed to allocate memory", __FUNCTION__);
++ rc = -ENOMEM;
++ goto failed;
++ }
++ memset(lnic, 0, sizeof(*lnic));
++ nic = &lnic->nic;
++
++ lnic->ev_handlers = &ev_handler;
++
++ /* OS specific hardware mappings */
++ rc = linux_efrm_nic_ctor(lnic, dev, reg_lock, flags, nic_options);
++ if (rc < 0) {
++ EFRM_ERR("%s: ERROR: initialisation failed", __FUNCTION__);
++ goto failed;
++ }
++
++ constructed = 1;
++
++ /* Tell the driver about the NIC - this needs to be done before the
++ resources managers get created below. Note we haven't initialised
++ the hardware yet, and I don't like doing this before the perhaps
++ unreliable hardware initialisation. However, there's quite a lot
++ of code to review if we wanted to hardware init before bringing
++ up the resource managers. */
++ rc = efrm_driver_register_nic(nic, nic_index++);
++ if (rc < 0) {
++ EFRM_ERR("%s: cannot register nic %d with nic error code %d",
++ __FUNCTION__, efrm_nic_table.nic_count, rc);
++ goto failed;
++ }
++ registered_nic = 1;
++
++ rc = efrm_nic_buffer_table_alloc(nic);
++ if (rc < 0)
++ goto failed;
++ buffers_allocated = 1;
++
++ /****************************************************/
++ /* hardware bringup */
++ /****************************************************/
++ /* Detecting hardware can be a slightly unreliable process;
++ we want to make sure that we maximise our chances, so we
++ loop a few times until all is good. */
++ for (count = 0; count < max_hardware_init_repeats; count++) {
++ rc = efhw_nic_init_hardware(nic, &ev_handler, mac_addr);
++ if (rc >= 0)
++ break;
++
++ /* pain */
++ EFRM_ERR
++ ("error - hardware initialisation failed code %d, "
++ "attempt %d of %d", rc, count + 1,
++ max_hardware_init_repeats);
++ }
++ if (rc < 0)
++ goto failed;
++
++ tasklet_init(&lnic->tasklet, efrm_tasklet, (ulong)nic);
++
++ /* set up interrupt handlers (hard-irq) */
++ nic->irq_handler = &efrm_handle_eventq_irq;
++
++ /* this device can now take management interrupts */
++ if (do_irq && !(nic->flags & NIC_FLAG_NO_INTERRUPT)) {
++ rc = linux_efrm_irq_ctor(lnic);
++ if (rc < 0) {
++ EFRM_ERR("Interrupt initialisation failed (%d)", rc);
++ goto failed;
++ }
++ efhw_nic_set_interrupt_moderation(nic, 0, irq_moderation);
++ efhw_nic_interrupt_enable(nic, 0);
++ }
++ EFRM_TRACE("interrupts are %sregistered", do_irq ? "" : "not ");
++
++#if EFRM_HAVE_IOMMU_LOCK
++ /* Bug 4560: We need the lock if there is memory which cannot be
++ * accessed by the card and there is an IOMMU to access it. In that
++ * case, the kernel will use the IOMMU to access the high memory. */
++ if ((dev->dma_mask >> PAGE_SHIFT) < max_pfn && !EFRM_NO_IOMMU)
++ efrm_need_iommu_lock = 1;
++#endif
++
++ *lnic_out = lnic;
++ EFRM_ASSERT(rc == 0);
++ ++n_nics_probed;
++ return 0;
++
++failed:
++ if (buffers_allocated)
++ efrm_nic_buffer_table_free(nic);
++ if (registered_nic)
++ efrm_driver_unregister_nic(nic);
++ if (constructed)
++ linux_efrm_nic_dtor(lnic);
++ kfree(lnic); /* safe in any case */
++ if (resources_init)
++ efrm_resources_fini();
++ return rc;
++}
++
++/****************************************************************************
++ *
++ * efrm_nic_del: Remove the nic from the resource driver structures
++ *
++ ****************************************************************************/
++void efrm_nic_del(struct linux_efhw_nic *lnic)
++{
++ struct efhw_nic *nic = &lnic->nic;
++
++ EFRM_TRACE("%s:", __FUNCTION__);
++ EFRM_ASSERT(nic);
++
++ efrm_driver_unregister_nic(nic);
++
++ /*
++ * Synchronise here with any running ISR.
++ * Remove the OS handler. There should be no IRQs being generated
++ * by our NIC at this point.
++ */
++ if (efhw_nic_have_functional_units(nic)) {
++ efhw_nic_close_interrupts(nic);
++ linux_efrm_irq_dtor(lnic);
++ tasklet_kill(&lnic->tasklet);
++ }
++
++ /* Close down hardware and free resources. */
++ linux_efrm_nic_dtor(lnic);
++ kfree(lnic);
++
++ if (--n_nics_probed == 0)
++ efrm_resources_fini();
++
++ EFRM_TRACE("NIC teardown: Done");
++}
++
++/****************************************************************************
++ *
++ * init_module: register as a PCI driver.
++ *
++ ****************************************************************************/
++static int init_sfc_resource(void)
++{
++ int rc = 0;
++
++ EFRM_TRACE("%s: RESOURCE driver starting", __FUNCTION__);
++
++ rc = efrm_driver_ctor();
++ if (rc < 0) {
++ EFRM_ERR("%s: efrm_driver_ctor: error %d", __FUNCTION__, rc);
++ goto fail_driver_ctor;
++ }
++
++ /* Register the driver so that our 'probe' function is called for
++ * each EtherFabric device in the system.
++ */
++ rc = efrm_driverlink_register();
++ if (rc == -ENODEV)
++ EFRM_ERR("%s: no devices found", __FUNCTION__);
++ if (rc < 0)
++ goto failed_driverlink;
++
++ if (efrm_install_proc_entries() != 0) {
++ /* Do not fail, but print a warning */
++ EFRM_WARN("%s: WARNING: failed to install /proc entries",
++ __FUNCTION__);
++ }
++
++ return 0;
++
++failed_driverlink:
++ /* No need to release resource managers here since they register
++ * destructors with the driver. */
++ efrm_driver_dtor();
++fail_driver_ctor:
++ EFRM_ASSERT(rc != 0);
++ return rc;
++}
++
++/****************************************************************************
++ *
++ * cleanup_module: module-removal entry-point
++ *
++ ****************************************************************************/
++static void cleanup_sfc_resource(void)
++{
++ efrm_uninstall_proc_entries();
++
++ efrm_driverlink_unregister();
++
++ /* Clean up char-driver specific initialisation.
++ - driver dtor can use both work queue and buffer table entries */
++ efrm_driver_dtor();
++
++ EFRM_TRACE("unloaded");
++}
++
++module_init(init_sfc_resource);
++module_exit(cleanup_sfc_resource);
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/resource_manager.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/resource_manager.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/resource_manager.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/resource_manager.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,263 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains generic code for resources and resource managers.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/debug.h>
++#include <ci/efrm/nic_table.h>
++#include <ci/efhw/iopage.h>
++#include <ci/efrm/driver_private.h>
++
++/**********************************************************************
++ * Internal stuff.
++ */
++
++#define EFRM_RM_TABLE_SIZE_INIT 256
++
++static int grow_table(struct efrm_resource_manager *rm, unsigned min_size)
++{
++ irq_flags_t lock_flags;
++ struct efrm_resource **table, **old_table;
++ unsigned new_size;
++
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm);
++
++ spin_lock_irqsave(&rm->rm_lock, lock_flags);
++
++ /* Check whether the size of the table increased whilst the lock was
++ * dropped. */
++ if (min_size <= rm->rm_table_size) {
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++ return 0;
++ }
++
++ new_size = rm->rm_table_size << 1;
++ if (new_size < min_size)
++ new_size = min_size;
++
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++ if (in_atomic()) {
++ EFRM_WARN("%s: in_atomic in grow_table()", __FUNCTION__);
++ EFRM_WARN("%s: allocating %u bytes", __FUNCTION__,
++ (unsigned)(new_size *
++ sizeof(struct efrm_resource *)));
++ return -ENOMEM;
++ }
++
++ table =
++ (struct efrm_resource **)vmalloc(new_size *
++ sizeof(struct efrm_resource *));
++ spin_lock_irqsave(&rm->rm_lock, lock_flags);
++
++ if (table == 0) {
++ EFRM_ERR("%s: out of memory in grow_table()", __FUNCTION__);
++ EFRM_ERR("%s: allocating %u bytes", __FUNCTION__,
++ (unsigned)(new_size *
++ sizeof(struct efrm_resource *)));
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++ return -ENOMEM;
++ }
++
++ /* Could have got bigger while we dropped the lock... */
++ if (new_size <= rm->rm_table_size) {
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++ vfree(table);
++ return 0;
++ }
++
++ memcpy(table, rm->rm_table, rm->rm_table_size * sizeof(*table));
++ memset(table + rm->rm_table_size, 0,
++ sizeof(*table) * (new_size - rm->rm_table_size));
++ /* remember old table so we can free the
++ memory after we drop the lock (bug 1040) */
++ old_table = rm->rm_table;
++ rm->rm_table = table;
++ rm->rm_table_size = new_size;
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++ vfree(old_table);
++
++ return 0;
++}
++
++/**********************************************************************
++ * struct efrm_resource_manager
++ */
++
++void efrm_resource_manager_dtor(struct efrm_resource_manager *rm)
++{
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm);
++
++ /* call destructor */
++ EFRM_DO_DEBUG(if (rm->rm_resources)
++ EFRM_ERR("%s: %s leaked %d resources",
++ __FUNCTION__, rm->rm_name, rm->rm_resources));
++ EFRM_ASSERT(rm->rm_resources == 0);
++
++ rm->rm_dtor(rm);
++
++ /* clear out things built by efrm_resource_manager_ctor */
++ spin_lock_destroy(&rm->rm_lock);
++ vfree(rm->rm_table);
++
++ /* and the free the memory */
++ EFRM_DO_DEBUG(memset(rm, 0, sizeof(*rm)));
++ kfree(rm);
++}
++
++/* Construct a resource manager. Resource managers are singletons. */
++int
++efrm_resource_manager_ctor(struct efrm_resource_manager *rm,
++ void (*dtor)(struct efrm_resource_manager *),
++ const char *name, unsigned type,
++ int initial_table_size)
++{
++ EFRM_ASSERT(rm);
++ EFRM_ASSERT(dtor);
++
++ rm->rm_name = name;
++ EFRM_DO_DEBUG(rm->rm_type = type);
++ rm->rm_dtor = dtor;
++ spin_lock_init(&rm->rm_lock);
++ rm->rm_resources = 0;
++ rm->rm_resources_hiwat = 0;
++
++ /* if not set then pick a number */
++ rm->rm_table_size = (initial_table_size) ?
++ initial_table_size : EFRM_RM_TABLE_SIZE_INIT;
++
++ rm->rm_table = vmalloc(rm->rm_table_size *
++ sizeof(struct efrm_resource *));
++
++ if (rm->rm_table == 0) {
++ spin_lock_destroy(&rm->rm_lock);
++ return -ENOMEM;
++ }
++ memset(rm->rm_table, 0, sizeof(*rm->rm_table) * rm->rm_table_size);
++
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm);
++ return 0;
++}
++
++int efrm_resource_manager_insert(struct efrm_resource *rs)
++{
++ irq_flags_t lock_flags;
++ struct efrm_resource_manager *rm;
++ int instance = EFRM_RESOURCE_INSTANCE(rs->rs_handle);
++
++ EFRM_ASSERT(EFRM_RESOURCE_TYPE(rs->rs_handle) < EFRM_RESOURCE_NUM);
++ rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
++ EFRM_ASSERT(EFRM_RESOURCE_TYPE(rs->rs_handle) == rm->rm_type);
++ EFRM_RESOURCE_ASSERT_VALID(rs, 0);
++
++ /* Put an entry in the resource table. */
++ spin_lock_irqsave(&rm->rm_lock, lock_flags);
++ if ((unsigned)instance >= rm->rm_table_size) {
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++ if (grow_table(rm, instance + 1) < 0)
++ return -ENOMEM;
++ spin_lock_irqsave(&rm->rm_lock, lock_flags);
++ }
++ EFRM_ASSERT(rm->rm_table_size > (unsigned)instance);
++ EFRM_ASSERT(rm->rm_table[instance] == NULL);
++ rm->rm_table[instance] = rs;
++ rm->rm_resources++;
++ if (rm->rm_resources > rm->rm_resources_hiwat)
++ rm->rm_resources_hiwat = rm->rm_resources;
++
++ /* Put the resource in the linked list. */
++ /* ?? broken list_add(&rm->rm_resources, &rs->rs_link); */
++ /* DJR wrote that it causes problem on driver unload, and DR tried
++ * it and saw (probably) this cause an assertion failure due to a
++ * bad link structure in
++ * /runbench/results/2005/09/22/0_DupTester_15-16-46 */
++
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++
++ return 0;
++}
++
++bool __efrm_resource_ref_count_zero(unsigned type, unsigned instance)
++{
++ /* This is rather nasty because when a resource's ref count goes to
++ * zero there is still a pointer to it in the [rm_table]. Thus
++ * arriving here does not guarantee that we have exclusive access
++ * to the resource and can free it. In fact the resource may
++ * already have been freed by another thread (after we dropped our
++ * ref, but before arriving here).
++ *
++ * At this point the only pointers to this resource should be [rs]
++ * and the one in [rm_table]. EXCEPT: Someone could have got in
++ * and looked-up the resource in the table before we got the lock.
++ * In this case the ref will have been hiked again.
++ *
++ * Therefore, if ref count is non-zero here, we shouldn't do
++ * anything, as someone else holds a ref to the resource, and will
++ * eventually release it.
++ *
++ * Otherwise, we zero-out the table entry. Therefore we have the
++ * only pointer to the resource, and can kill it safely.
++ */
++ struct efrm_resource_manager *rm = efrm_rm_table[type];
++ irq_flags_t lock_flags;
++ struct efrm_resource *rs;
++ bool do_free = false;
++
++ EFRM_TRACE("efrm_resource_ref_count_zero: type=%d instance=%d",
++ rm->rm_type, instance);
++
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm);
++ EFRM_ASSERT(rm->rm_table_size > instance);
++
++ spin_lock_irqsave(&rm->rm_lock, lock_flags);
++
++ rs = rm->rm_table[instance];
++ if (rs != NULL) {
++ do_free = atomic_read(&rs->rs_ref_count) == 0;
++ if (do_free) {
++ EFRM_ASSERT(rm->rm_resources > 0);
++ --rm->rm_resources;
++ rm->rm_table[instance] = 0;
++ }
++ }
++
++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
++
++ return do_free;
++}
++EXPORT_SYMBOL(__efrm_resource_ref_count_zero);
++
++/*
++ * vi: sw=8:ai:aw
++ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/resources.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/resources.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/resources.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/resources.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,94 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains resource managers initialisation functions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/private.h>
++#include <ci/efrm/buffer_table.h>
++
++int
++efrm_resources_init(const struct vi_resource_dimensions *vi_res_dim,
++ int buffer_table_min, int buffer_table_max)
++{
++ int i, rc;
++
++ rc = efrm_buffer_table_ctor(buffer_table_min, buffer_table_max);
++ if (rc != 0)
++ return rc;
++
++ /* Create resources in the correct order */
++ for (i = 0; i < EFRM_RESOURCE_NUM; ++i) {
++ struct efrm_resource_manager **rmp = &efrm_rm_table[i];
++
++ EFRM_ASSERT(*rmp == NULL);
++ switch (i) {
++ case EFRM_RESOURCE_VI:
++ rc = efrm_create_vi_resource_manager(rmp,
++ vi_res_dim);
++ break;
++ case EFRM_RESOURCE_FILTER:
++ rc = efrm_create_filter_resource_manager(rmp);
++ break;
++ case EFRM_RESOURCE_IOBUFSET:
++ rc = efrm_create_iobufset_resource_manager(rmp);
++ break;
++ default:
++ rc = 0;
++ break;
++ }
++
++ if (rc < 0) {
++ EFRM_ERR("%s: failed type=%d (%d)",
++ __FUNCTION__, i, rc);
++ efrm_buffer_table_dtor();
++ return rc;
++ }
++ }
++
++ return 0;
++}
++
++void efrm_resources_fini(void)
++{
++ int i;
++
++ for (i = EFRM_RESOURCE_NUM - 1; i >= 0; --i)
++ if (efrm_rm_table[i]) {
++ efrm_resource_manager_dtor(efrm_rm_table[i]);
++ efrm_rm_table[i] = NULL;
++ }
++
++ efrm_buffer_table_dtor();
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/vi_resource_alloc.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/vi_resource_alloc.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/vi_resource_alloc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/vi_resource_alloc.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,876 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains allocation of VI resources.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/nic_table.h>
++#include <ci/efhw/iopage.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efhw/public.h>
++#include <ci/efhw/falcon.h>
++#include <ci/efrm/private.h>
++#include <ci/efrm/buffer_table.h>
++#include <ci/efrm/vi_resource_private.h>
++
++/*** Data definitions ****************************************************/
++
++static const char *dmaq_names[] = { "TX", "RX" };
++
++struct vi_resource_manager *efrm_vi_manager;
++
++/*** Forward references **************************************************/
++
++static int
++efrm_vi_resource_alloc_or_free(int alloc, struct vi_resource *evq_virs,
++ uint16_t vi_flags, int32_t evq_capacity,
++ int32_t txq_capacity, int32_t rxq_capacity,
++ uint8_t tx_q_tag, uint8_t rx_q_tag,
++ struct vi_resource **virs_in_out);
++
++/*** Reference count handling ********************************************/
++
++static inline void efrm_vi_rm_get_ref(struct vi_resource *virs)
++{
++ atomic_inc(&virs->evq_refs);
++}
++
++static inline void efrm_vi_rm_drop_ref(struct vi_resource *virs)
++{
++ EFRM_ASSERT(atomic_read(&virs->evq_refs) != 0);
++ if (atomic_dec_and_test(&virs->evq_refs))
++ efrm_vi_resource_alloc_or_free(false, NULL, 0, 0, 0, 0, 0, 0,
++ &virs);
++}
++
++/*** Instance numbers ****************************************************/
++
++static inline int efrm_vi_rm_alloc_id(uint16_t vi_flags, int32_t evq_capacity)
++{
++ irq_flags_t lock_flags;
++ int instance;
++ int rc;
++
++ if (efrm_nic_table.a_nic == NULL) /* ?? FIXME: surely not right */
++ return -ENODEV;
++
++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ /* Falcon A1 RX phys addr wierdness. */
++ if (efrm_nic_table.a_nic->devtype.variant == 'A' &&
++ (vi_flags & EFHW_VI_RX_PHYS_ADDR_EN)) {
++ if (vi_flags & EFHW_VI_JUMBO_EN) {
++ /* Falcon-A cannot do phys + scatter. */
++ EFRM_WARN
++ ("%s: falcon-A does not support phys+scatter mode",
++ __FUNCTION__);
++ instance = -1;
++ } else if (efrm_vi_manager->iscsi_dmaq_instance_is_free
++ && evq_capacity == 0) {
++ /* Falcon-A has a single RXQ that gives the correct
++ * semantics for physical addressing. However, it
++ * happens to have the same instance number as the
++ * 'char' event queue, so we cannot also hand out
++ * the event queue. */
++ efrm_vi_manager->iscsi_dmaq_instance_is_free = false;
++ instance = FALCON_A1_ISCSI_DMAQ;
++ } else {
++ EFRM_WARN("%s: iSCSI receive queue not free",
++ __FUNCTION__);
++ instance = -1;
++ }
++ goto unlock_out;
++ }
++
++ if (vi_flags & EFHW_VI_RM_WITH_INTERRUPT) {
++ rc = __kfifo_get(efrm_vi_manager->instances_with_interrupt,
++ (unsigned char *)&instance, sizeof(instance));
++ if (rc != sizeof(instance)) {
++ EFRM_ASSERT(rc == 0);
++ instance = -1;
++ }
++ goto unlock_out;
++ }
++
++ /* Otherwise a normal run-of-the-mill VI. */
++ rc = __kfifo_get(efrm_vi_manager->instances_with_timer,
++ (unsigned char *)&instance, sizeof(instance));
++ if (rc != sizeof(instance)) {
++ EFRM_ASSERT(rc == 0);
++ instance = -1;
++ }
++
++unlock_out:
++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
++ return instance;
++}
++
++static void efrm_vi_rm_free_id(int instance)
++{
++ irq_flags_t lock_flags;
++ struct kfifo *instances;
++
++ if (efrm_nic_table.a_nic == NULL) /* ?? FIXME: surely not right */
++ return;
++
++ if (efrm_nic_table.a_nic->devtype.variant == 'A' &&
++ instance == FALCON_A1_ISCSI_DMAQ) {
++ EFRM_ASSERT(efrm_vi_manager->iscsi_dmaq_instance_is_free ==
++ false);
++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
++ efrm_vi_manager->iscsi_dmaq_instance_is_free = true;
++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock,
++ lock_flags);
++ } else {
++ if (instance >= efrm_vi_manager->with_timer_base &&
++ instance < efrm_vi_manager->with_timer_limit) {
++ instances = efrm_vi_manager->instances_with_timer;
++ } else {
++ EFRM_ASSERT(instance >=
++ efrm_vi_manager->with_interrupt_base);
++ EFRM_ASSERT(instance <
++ efrm_vi_manager->with_interrupt_limit);
++ instances = efrm_vi_manager->instances_with_interrupt;
++ }
++
++ EFRM_VERIFY_EQ(kfifo_put(instances, (unsigned char *)&instance,
++ sizeof(instance)), sizeof(instance));
++ }
++}
++
++/*** Queue sizes *********************************************************/
++
++/* NB. This should really take a nic as an argument, but that makes
++ * the buffer table allocation difficult. */
++uint32_t efrm_vi_rm_evq_bytes(struct vi_resource *virs
++ /*,struct efhw_nic *nic */ )
++{
++ return virs->evq_capacity * sizeof(efhw_event_t);
++}
++EXPORT_SYMBOL(efrm_vi_rm_evq_bytes);
++
++/* NB. This should really take a nic as an argument, but that makes
++ * the buffer table allocation difficult. */
++uint32_t efrm_vi_rm_txq_bytes(struct vi_resource *virs
++ /*,struct efhw_nic *nic */ )
++{
++ return virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] *
++ FALCON_DMA_TX_DESC_BYTES;
++}
++EXPORT_SYMBOL(efrm_vi_rm_txq_bytes);
++
++/* NB. This should really take a nic as an argument, but that makes
++ * the buffer table allocation difficult. */
++uint32_t efrm_vi_rm_rxq_bytes(struct vi_resource *virs
++ /*,struct efhw_nic *nic */ )
++{
++ uint32_t bytes_per_desc = ((virs->flags & EFHW_VI_RX_PHYS_ADDR_EN)
++ ? FALCON_DMA_RX_PHYS_DESC_BYTES
++ : FALCON_DMA_RX_BUF_DESC_BYTES);
++ return virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] * bytes_per_desc;
++}
++EXPORT_SYMBOL(efrm_vi_rm_rxq_bytes);
++
++static int choose_size(int size_rq, unsigned sizes)
++{
++ int size;
++
++ /* size_rq < 0 means default, but we interpret this as 'minimum'. */
++
++ for (size = 256;; size <<= 1)
++ if ((sizes & ~((size - 1) | size)) == 0)
++ return -1;
++ else if ((size & sizes) && size >= size_rq)
++ return size;
++}
++
++static int
++efrm_vi_rm_adjust_alloc_request(struct vi_resource *virs, struct efhw_nic *nic)
++{
++ int capacity;
++
++ EFRM_ASSERT(nic->efhw_func);
++
++ if (virs->evq_capacity) {
++ capacity = choose_size(virs->evq_capacity, nic->evq_sizes);
++ if (capacity < 0) {
++ EFRM_ERR("vi_resource: bad evq size %d (supported=%x)",
++ virs->evq_capacity, nic->evq_sizes);
++ return -E2BIG;
++ }
++ virs->evq_capacity = capacity;
++ }
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) {
++ capacity =
++ choose_size(virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX],
++ nic->txq_sizes);
++ if (capacity < 0) {
++ EFRM_ERR("vi_resource: bad txq size %d (supported=%x)",
++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX],
++ nic->txq_sizes);
++ return -E2BIG;
++ }
++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] = capacity;
++ }
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) {
++ capacity =
++ choose_size(virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX],
++ nic->rxq_sizes);
++ if (capacity < 0) {
++ EFRM_ERR("vi_resource: bad rxq size %d (supported=%x)",
++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX],
++ nic->rxq_sizes);
++ return -E2BIG;
++ }
++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] = capacity;
++ }
++
++ return 0;
++}
++
++/* remove the reference to the event queue in this VI resource and decrement
++ the event queue's use count */
++static inline void efrm_vi_rm_detach_evq(struct vi_resource *virs)
++{
++ struct vi_resource *evq_virs;
++
++ EFRM_ASSERT(virs != NULL);
++
++ evq_virs = virs->evq_virs;
++
++ if (evq_virs != NULL) {
++ virs->evq_virs = NULL;
++ if (evq_virs == virs) {
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT
++ " had internal event queue ", __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
++ } else {
++ efrm_vi_rm_drop_ref(evq_virs);
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " had event queue "
++ EFRM_RESOURCE_FMT, __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
++ EFRM_RESOURCE_PRI_ARG(evq_virs->rs.
++ rs_handle));
++ }
++ } else {
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT
++ " had no event queue (nothing to do)",
++ __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
++ }
++}
++
++/*** Buffer Table allocations ********************************************/
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++static int
++efrm_vi_rm_alloc_or_free_buffer_table(struct vi_resource *virs, bool is_alloc)
++{
++ uint32_t bytes;
++ int page_order;
++ int rc;
++
++ if (!is_alloc)
++ goto destroy;
++
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) {
++ bytes = efrm_vi_rm_txq_bytes(virs);
++ page_order = get_order(bytes);
++ rc = efrm_buffer_table_alloc(page_order,
++ (virs->dmaq_buf_tbl_alloc +
++ EFRM_VI_RM_DMA_QUEUE_TX));
++ if (rc != 0) {
++ EFRM_TRACE
++ ("%s: Error %d allocating TX buffer table entry",
++ __FUNCTION__, rc);
++ goto fail_txq_alloc;
++ }
++ }
++
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) {
++ bytes = efrm_vi_rm_rxq_bytes(virs);
++ page_order = get_order(bytes);
++ rc = efrm_buffer_table_alloc(page_order,
++ (virs->dmaq_buf_tbl_alloc +
++ EFRM_VI_RM_DMA_QUEUE_RX));
++ if (rc != 0) {
++ EFRM_TRACE
++ ("%s: Error %d allocating RX buffer table entry",
++ __FUNCTION__, rc);
++ goto fail_rxq_alloc;
++ }
++ }
++ return 0;
++
++destroy:
++ rc = 0;
++
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) {
++ efrm_buffer_table_free(&virs->
++ dmaq_buf_tbl_alloc
++ [EFRM_VI_RM_DMA_QUEUE_RX]);
++ }
++fail_rxq_alloc:
++
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) {
++ efrm_buffer_table_free(&virs->
++ dmaq_buf_tbl_alloc
++ [EFRM_VI_RM_DMA_QUEUE_TX]);
++ }
++fail_txq_alloc:
++
++ return rc;
++}
++
++#endif /* defined(__CI_HARDWARE_CONFIG_FALCON__) */
++
++/*** Per-NIC allocations *************************************************/
++
++static inline int
++efrm_vi_rm_init_evq(struct vi_resource *virs, int nic_index)
++{
++ int rc;
++ struct efhw_nic *nic = efrm_nic_table.nic[nic_index];
++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++ struct eventq_resource_hardware *evq_hw =
++ &virs->nic_info[nic_index].evq_pages;
++ uint32_t buf_bytes = efrm_vi_rm_evq_bytes(virs);
++
++ if (virs->evq_capacity == 0)
++ return 0;
++ evq_hw->capacity = virs->evq_capacity;
++
++ /* Allocate buffer table entries to map onto the iobuffer. This
++ * currently allocates its own buffer table entries on Falcon which is
++ * a bit wasteful on a multi-NIC system. */
++ evq_hw->buf_tbl_alloc.base = (unsigned)-1;
++ rc = efrm_buffer_table_alloc(get_order(buf_bytes),
++ &evq_hw->buf_tbl_alloc);
++ if (rc < 0) {
++ EFHW_WARN("%s: failed (%d) to alloc %d buffer table entries",
++ __FUNCTION__, rc, get_order(buf_bytes));
++ return rc;
++ }
++
++ /* Allocate the event queue memory. */
++ rc = efhw_nic_event_queue_alloc_iobuffer(nic, evq_hw, instance,
++ buf_bytes);
++ if (rc != 0) {
++ EFRM_ERR("%s: Error allocating iobuffer: %d", __FUNCTION__, rc);
++ efrm_buffer_table_free(&evq_hw->buf_tbl_alloc);
++ return rc;
++ }
++
++ /* Initialise the event queue hardware */
++ efhw_nic_event_queue_enable(nic, instance, virs->evq_capacity,
++ efhw_iopages_dma_addr(&evq_hw->iobuff) +
++ evq_hw->iobuff_off,
++ evq_hw->buf_tbl_alloc.base);
++
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " capacity=%u", __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
++ virs->evq_capacity);
++
++#if defined(__ia64__)
++ /* Page size may be large, so for now just increase the
++ * size of the requested evq up to a round number of
++ * pages
++ */
++ buf_bytes = CI_ROUND_UP(buf_bytes, PAGE_SIZE);
++#endif
++ EFRM_ASSERT(buf_bytes % PAGE_SIZE == 0);
++
++ virs->mem_mmap_bytes += buf_bytes;
++
++ return 0;
++}
++
++static inline void
++efrm_vi_rm_fini_evq(struct vi_resource *virs, int nic_index)
++{
++ struct efhw_nic *nic = efrm_nic_table.nic[nic_index];
++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++ struct vi_resource_nic_info *nic_info = &virs->nic_info[nic_index];
++
++ if (virs->evq_capacity == 0)
++ return;
++
++ /* Zero the timer-value for this queue.
++ And Tell NIC to stop using this event queue. */
++ efhw_nic_event_queue_disable(nic, instance, 0);
++
++ if (nic_info->evq_pages.buf_tbl_alloc.base != (unsigned)-1)
++ efrm_buffer_table_free(&nic_info->evq_pages.buf_tbl_alloc);
++
++ efhw_iopages_free(nic, &nic_info->evq_pages.iobuff);
++}
++
++/*! FIXME: we should make sure this number is never zero (=> unprotected) */
++/*! FIXME: put this definition in a relevant header (e.g. as (evqid)+1) */
++#define EFAB_EVQ_OWNER_ID(evqid) ((evqid))
++
++void
++efrm_vi_rm_init_dmaq(struct vi_resource *virs, int queue_type,
++ struct efhw_nic *nic)
++{
++ int instance;
++ struct vi_resource *evq_virs;
++ int evq_instance;
++ efhw_buffer_addr_t buf_addr;
++
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++ evq_virs = virs->evq_virs;
++ evq_instance = EFRM_RESOURCE_INSTANCE(evq_virs->rs.rs_handle);
++
++ buf_addr = virs->dmaq_buf_tbl_alloc[queue_type].base;
++
++ if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX) {
++ efhw_nic_dmaq_tx_q_init(nic,
++ instance, /* dmaq */
++ evq_instance, /* evq */
++ EFAB_EVQ_OWNER_ID(evq_instance), /* owner */
++ virs->dmaq_tag[queue_type], /* tag */
++ virs->dmaq_capacity[queue_type], /* size of queue */
++ buf_addr, /* buffer index */
++ virs->flags); /* user specified Q attrs */
++ } else {
++ efhw_nic_dmaq_rx_q_init(nic,
++ instance, /* dmaq */
++ evq_instance, /* evq */
++ EFAB_EVQ_OWNER_ID(evq_instance), /* owner */
++ virs->dmaq_tag[queue_type], /* tag */
++ virs->dmaq_capacity[queue_type], /* size of queue */
++ buf_addr, /* buffer index */
++ virs->flags); /* user specified Q attrs */
++ }
++}
++
++static int
++efrm_vi_rm_init_or_fini_dmaq(struct vi_resource *virs,
++ int queue_type, int init, int nic_index)
++{
++ int rc;
++ struct efhw_nic *nic = efrm_nic_table.nic[nic_index];
++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++ uint32_t buf_bytes;
++ struct vi_resource *evq_virs;
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ struct vi_resource_nic_info *nic_info = &virs->nic_info[nic_index];
++ int page_order;
++ uint32_t num_pages;
++ efhw_iopages_t *iobuff;
++#endif
++
++ if (!init)
++ goto destroy;
++
++ /* Ignore disabled queues. */
++ if (virs->dmaq_capacity[queue_type] == 0) {
++ if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX)
++ efhw_nic_dmaq_tx_q_disable(nic, instance);
++ else
++ efhw_nic_dmaq_rx_q_disable(nic, instance);
++ return 0;
++ }
++
++ buf_bytes = (queue_type == EFRM_VI_RM_DMA_QUEUE_TX
++ ? efrm_vi_rm_txq_bytes(virs)
++ : efrm_vi_rm_rxq_bytes(virs));
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ page_order = get_order(buf_bytes);
++
++ rc = efhw_iopages_alloc(nic, &nic_info->dmaq_pages[queue_type],
++ page_order);
++ if (rc != 0) {
++ EFRM_ERR("%s: Failed to allocate %s DMA buffer.", __FUNCTION__,
++ dmaq_names[queue_type]);
++ goto fail_iopages;
++ }
++
++ num_pages = 1 << page_order;
++ iobuff = &nic_info->dmaq_pages[queue_type];
++ efhw_nic_buffer_table_set_n(nic,
++ virs->dmaq_buf_tbl_alloc[queue_type].base,
++ efhw_iopages_dma_addr(iobuff),
++ EFHW_NIC_PAGE_SIZE, 0, num_pages, 0);
++
++ falcon_nic_buffer_table_confirm(nic);
++
++ virs->mem_mmap_bytes += round_up(buf_bytes, PAGE_SIZE);
++#endif /* __CI_HARDWARE_CONFIG_FALCON__ */
++
++ evq_virs = virs->evq_virs;
++ EFRM_ASSERT(evq_virs);
++
++ /* Make sure there is an event queue. */
++ if (evq_virs->evq_capacity <= 0) {
++ EFRM_ERR("%s: Cannot use empty event queue for %s DMA",
++ __FUNCTION__, dmaq_names[queue_type]);
++ rc = -EINVAL;
++ goto fail_evq;
++ }
++
++ efrm_vi_rm_init_dmaq(virs, queue_type, nic);
++
++ return 0;
++
++destroy:
++ rc = 0;
++
++ /* Ignore disabled queues. */
++ if (virs->dmaq_capacity[queue_type] == 0)
++ return 0;
++
++ /* No need to disable the queue here. Nobody is using it anyway. */
++
++fail_evq:
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ efhw_iopages_free(nic, &nic_info->dmaq_pages[queue_type]);
++fail_iopages:
++#endif
++
++ return rc;
++}
++
++static int
++efrm_vi_rm_init_or_fini_nic(struct vi_resource *virs, int init, int nic_index)
++{
++ struct vi_resource *evq_virs;
++ int rc;
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++#ifndef NDEBUG
++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++#endif
++#endif
++
++ if (!init)
++ goto destroy;
++
++ evq_virs = virs->evq_virs;
++ if (evq_virs != virs) {
++ if (!efrm_nic_set_read(&evq_virs->nic_set, nic_index)) {
++ /* Ignore this NIC. It's not supported by the event
++ * queue. */
++ return 0;
++ }
++ }
++
++ rc = efrm_vi_rm_init_evq(virs, nic_index);
++ if (rc != 0)
++ goto fail_evq;
++
++ rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
++ init, nic_index);
++ if (rc != 0)
++ goto fail_txq;
++
++ rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
++ init, nic_index);
++ if (rc != 0)
++ goto fail_rxq;
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ /* Allocate space for the control page. */
++ EFRM_ASSERT(falcon_tx_dma_page_offset(instance) < PAGE_SIZE);
++ EFRM_ASSERT(falcon_rx_dma_page_offset(instance) < PAGE_SIZE);
++ EFRM_ASSERT(falcon_timer_page_offset(instance) < PAGE_SIZE);
++ virs->bar_mmap_bytes += PAGE_SIZE;
++#endif
++
++ /* Mark the NIC as having been initialised. */
++ efrm_nic_set_write(&virs->nic_set, nic_index, true);
++
++ return 0;
++
++destroy:
++ rc = 0;
++
++ efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
++ false, nic_index);
++fail_rxq:
++
++ efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
++ false, nic_index);
++fail_txq:
++
++ efrm_vi_rm_fini_evq(virs, nic_index);
++fail_evq:
++
++ /* Mark the NIC as having been finalised. */
++ efrm_nic_set_write(&virs->nic_set, nic_index, false);
++ EFRM_ASSERT(rc != 0 || !init);
++
++ return rc;
++}
++
++static int
++efrm_vi_resource_alloc_or_free(int alloc, struct vi_resource *evq_virs,
++ uint16_t vi_flags, int32_t evq_capacity,
++ int32_t txq_capacity, int32_t rxq_capacity,
++ uint8_t tx_q_tag, uint8_t rx_q_tag,
++ struct vi_resource **virs_in_out)
++{
++ struct vi_resource *virs;
++ int rc;
++ int instance;
++ struct efhw_nic *nic;
++ int nic_i;
++
++ EFRM_ASSERT(virs_in_out);
++ EFRM_ASSERT(efrm_vi_manager);
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_vi_manager->rm);
++
++ if (!alloc)
++ goto destroy;
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ rx_q_tag &= (1 << TX_DESCQ_LABEL_WIDTH) - 1;
++ tx_q_tag &= (1 << RX_DESCQ_LABEL_WIDTH) - 1;
++#endif
++
++ virs = kmalloc(sizeof(*virs), GFP_KERNEL);
++ if (virs == NULL) {
++ EFRM_ERR("%s: Error allocating VI resource object",
++ __FUNCTION__);
++ rc = -ENOMEM;
++ goto fail_alloc;
++ }
++ memset(virs, 0, sizeof(*virs));
++
++ /* Some macros make the assumption that the struct efrm_resource is
++ * the first member of a struct vi_resource. */
++ EFRM_ASSERT(&virs->rs == (struct efrm_resource *) (virs));
++
++ instance = efrm_vi_rm_alloc_id(vi_flags, evq_capacity);
++ if (instance < 0) {
++ /* Clear out the close list... */
++ efrm_vi_rm_salvage_flushed_vis();
++ instance = efrm_vi_rm_alloc_id(vi_flags, evq_capacity);
++ if (instance >= 0)
++ EFRM_TRACE("%s: Salvaged a closed VI.", __FUNCTION__);
++ }
++
++ if (instance < 0) {
++ /* Could flush resources and try again here. */
++ EFRM_ERR("%s: Out of appropriate VI resources", __FUNCTION__);
++ rc = -EBUSY;
++ goto fail_alloc_id;
++ }
++
++ EFRM_TRACE("%s: new VI ID %d", __FUNCTION__, instance);
++ efrm_resource_init(&virs->rs, EFRM_RESOURCE_VI, instance);
++
++ /* Start with one reference. Any external VIs using the EVQ of this
++ * resource will increment this reference rather than the resource
++ * reference to avoid DMAQ flushes from waiting for other DMAQ
++ * flushes to complete. When the resource reference goes to zero,
++ * the DMAQ flush happens. When the flush completes, this reference
++ * is decremented. When this reference reaches zero, the instance
++ * is freed. */
++ atomic_set(&virs->evq_refs, 1);
++
++ efrm_nic_set_clear(&virs->nic_set);
++
++ virs->bar_mmap_bytes = 0;
++ virs->mem_mmap_bytes = 0;
++ virs->evq_capacity = evq_capacity;
++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] = txq_capacity;
++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] = rxq_capacity;
++ virs->dmaq_tag[EFRM_VI_RM_DMA_QUEUE_TX] = tx_q_tag;
++ virs->dmaq_tag[EFRM_VI_RM_DMA_QUEUE_RX] = rx_q_tag;
++ virs->flags = vi_flags;
++
++ INIT_LIST_HEAD(&virs->tx_flush_link);
++ INIT_LIST_HEAD(&virs->rx_flush_link);
++ efrm_nic_set_clear(&virs->tx_flush_nic_set);
++ efrm_nic_set_clear(&virs->rx_flush_nic_set);
++
++ memset(&efrm_vi_manager->evq_infos[instance], 0,
++ sizeof(struct vi_resource_evq_info));
++ efrm_vi_manager->evq_infos[instance].evq_virs = virs;
++
++ /* Adjust the queue sizes. */
++ rc = 0;
++ EFRM_FOR_EACH_NIC(nic_i, nic)
++ if (rc == 0)
++ rc = efrm_vi_rm_adjust_alloc_request(virs, nic);
++ if (rc != 0)
++ goto fail_adjust_request;
++
++ /* Attach the EVQ early so that we can ensure that the NIC sets
++ * match. */
++ if (evq_virs == NULL) {
++ evq_virs = virs;
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT
++ " has no external event queue", __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
++ } else {
++ /* Make sure the resource managers are the same. */
++ if (EFRM_RESOURCE_TYPE(evq_virs->rs.rs_handle) !=
++ EFRM_RESOURCE_VI) {
++ EFRM_ERR("%s: Mismatched owner for event queue VI "
++ EFRM_RESOURCE_FMT, __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(evq_virs->rs.rs_handle));
++ return -EINVAL;
++ }
++ EFRM_ASSERT(atomic_read(&evq_virs->evq_refs) != 0);
++ efrm_vi_rm_get_ref(evq_virs);
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " uses event queue "
++ EFRM_RESOURCE_FMT,
++ __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
++ EFRM_RESOURCE_PRI_ARG(evq_virs->rs.rs_handle));
++ }
++ virs->evq_virs = evq_virs;
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ rc = efrm_vi_rm_alloc_or_free_buffer_table(virs, true);
++ if (rc != 0)
++ goto fail_buffer_table;
++#endif
++
++ rc = 0;
++ EFRM_FOR_EACH_NIC(nic_i, nic)
++ if (rc == 0)
++ /* This updates virs->nic_set for the NICs which need
++ * finalising. */
++ rc = efrm_vi_rm_init_or_fini_nic(virs, true, nic_i);
++ if (rc != 0)
++ goto fail_init_nic;
++
++ /* Put it into the resource manager's table. */
++ rc = efrm_resource_manager_insert(&virs->rs);
++ if (rc != 0) {
++ if (atomic_dec_and_test(&virs->rs.rs_ref_count))
++ efrm_vi_resource_free(virs);
++ return rc;
++ }
++
++ *virs_in_out = virs;
++ EFRM_TRACE("%s: Allocated " EFRM_RESOURCE_FMT, __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
++ return 0;
++
++destroy:
++ virs = *virs_in_out;
++ EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 1);
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++ EFRM_TRACE("%s: Freeing %d", __FUNCTION__,
++ EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle));
++
++ /* Destroying the VI. The reference count must be zero. */
++ EFRM_ASSERT(atomic_read(&virs->evq_refs) == 0);
++
++ /* The EVQ should have gone (and DMA disabled) so that this
++ * function can't be re-entered to destroy the EVQ VI. */
++ EFRM_ASSERT(virs->evq_virs == NULL);
++ rc = 0;
++
++fail_init_nic:
++ EFRM_FOR_EACH_NIC_IN_SET(&virs->nic_set, nic_i, nic)
++ efrm_vi_rm_init_or_fini_nic(virs, false, nic_i);
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ efrm_vi_rm_alloc_or_free_buffer_table(virs, false);
++fail_buffer_table:
++#endif
++
++ efrm_vi_rm_detach_evq(virs);
++
++fail_adjust_request:
++
++ EFRM_ASSERT(virs->evq_callback_fn == NULL);
++ memset(&efrm_vi_manager->evq_infos[instance], 0,
++ sizeof(struct vi_resource_evq_info));
++ EFRM_TRACE("%s: delete VI ID %d", __FUNCTION__, instance);
++ efrm_vi_rm_free_id(instance);
++fail_alloc_id:
++
++ EFRM_DO_DEBUG(memset(virs, 0, sizeof(*virs)));
++ kfree(virs);
++fail_alloc:
++ *virs_in_out = NULL;
++
++ return rc;
++}
++
++/*** Resource object ****************************************************/
++
++int
++efrm_vi_resource_alloc(struct vi_resource *evq_virs,
++ uint16_t vi_flags, int32_t evq_capacity,
++ int32_t txq_capacity, int32_t rxq_capacity,
++ uint8_t tx_q_tag, uint8_t rx_q_tag,
++ struct vi_resource **virs_out,
++ uint32_t *out_io_mmap_bytes,
++ uint32_t *out_mem_mmap_bytes,
++ uint32_t *out_txq_capacity, uint32_t *out_rxq_capacity)
++{
++ int rc;
++ rc = efrm_vi_resource_alloc_or_free(true, evq_virs, vi_flags,
++ evq_capacity, txq_capacity,
++ rxq_capacity, tx_q_tag, rx_q_tag,
++ virs_out);
++ if (rc == 0) {
++ if (out_io_mmap_bytes != NULL)
++ *out_io_mmap_bytes = (*virs_out)->bar_mmap_bytes;
++ if (out_mem_mmap_bytes != NULL)
++ *out_mem_mmap_bytes = (*virs_out)->mem_mmap_bytes;
++ if (out_txq_capacity != NULL)
++ *out_txq_capacity =
++ (*virs_out)->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX];
++ if (out_rxq_capacity != NULL)
++ *out_rxq_capacity =
++ (*virs_out)->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX];
++ }
++
++ return rc;
++}
++EXPORT_SYMBOL(efrm_vi_resource_alloc);
++
++void efrm_vi_rm_free_flushed_resource(struct vi_resource *virs)
++{
++ EFRM_ASSERT(virs != NULL);
++ EFRM_ASSERT(atomic_read(&virs->rs.rs_ref_count) == 0);
++
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
++ /* release the associated event queue then drop our own reference
++ * count */
++ efrm_vi_rm_detach_evq(virs);
++ efrm_vi_rm_drop_ref(virs);
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/vi_resource_event.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/vi_resource_event.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/vi_resource_event.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/vi_resource_event.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,232 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains event handling for VI resource.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/nic_table.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efhw/eventq.h>
++#include <ci/efrm/private.h>
++#include <ci/efrm/vi_resource_private.h>
++
++void
++efrm_eventq_request_wakeup(struct vi_resource *virs, unsigned current_ptr,
++ unsigned nic_index)
++{
++ struct efhw_nic *nic;
++ int next_i;
++ EFRM_ASSERT(efrm_nic_set_read(&virs->nic_set, nic_index));
++ nic = efrm_nic_table.nic[nic_index];
++ EFRM_ASSERT(nic);
++ next_i = ((current_ptr / sizeof(efhw_event_t)) &
++ (virs->evq_capacity - 1));
++
++ efhw_nic_wakeup_request(nic, efrm_eventq_dma_addr(virs, nic_index),
++ next_i,
++ EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle));
++}
++EXPORT_SYMBOL(efrm_eventq_request_wakeup);
++
++void efrm_eventq_reset(struct vi_resource *virs, int nic_index)
++{
++ struct efhw_nic *nic = efrm_nic_table.nic[nic_index];
++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++ EFRM_ASSERT(virs->evq_capacity != 0);
++ EFRM_ASSERT(efrm_nic_set_read(&virs->nic_set, nic_index));
++
++ /* FIXME: Protect against concurrent resets. */
++
++ efhw_nic_event_queue_disable(nic, instance, 0);
++
++ memset(efrm_eventq_base(virs, nic_index), EFHW_CLEAR_EVENT_VALUE,
++ efrm_eventq_bytes(virs, nic_index));
++ efhw_nic_event_queue_enable(nic, instance, virs->evq_capacity,
++ efrm_eventq_dma_addr(virs, nic_index),
++ virs->nic_info[nic_index].evq_pages.
++ buf_tbl_alloc.base);
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
++}
++EXPORT_SYMBOL(efrm_eventq_reset);
++
++int
++efrm_eventq_register_callback(struct vi_resource *virs,
++ void (*handler) (void *, int,
++ struct efhw_nic *nic),
++ void *arg)
++{
++ int instance;
++ int bit;
++
++ EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
++ EFRM_ASSERT(virs->evq_capacity != 0);
++
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++ /* The handler can be set only once. */
++ bit = test_and_set_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
++ &efrm_vi_manager->evq_infos[instance].evq_state);
++ if (bit)
++ return -EBUSY;
++
++ /* Store the details. The order is important here. */
++ virs->evq_callback_arg = arg;
++ virs->evq_callback_fn = handler;
++
++ return 0;
++}
++EXPORT_SYMBOL(efrm_eventq_register_callback);
++
++void efrm_eventq_kill_callback(struct vi_resource *virs)
++{
++ int nic_i, instance;
++ struct efhw_nic *nic;
++ struct vi_resource_evq_info *evq_info;
++ int32_t evq_state;
++ int bit;
++
++ EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
++ EFRM_ASSERT(virs->evq_capacity != 0);
++
++ /* Clean out the callback so a new one can be installed. */
++ virs->evq_callback_fn = NULL;
++
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++ evq_info = &efrm_vi_manager->evq_infos[instance];
++
++ /* Disable the event queue. */
++ EFRM_FOR_EACH_NIC_IN_SET(&virs->nic_set, nic_i, nic)
++ efhw_nic_event_queue_disable(nic, instance, /*timer_only */ 1);
++
++ /* Disable the callback. */
++ bit = test_and_clear_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
++ &evq_info->evq_state);
++ EFRM_ASSERT(bit); /* do not call me twice! */
++
++ /* Spin until the callback is complete. */
++ do {
++ rmb();
++
++ udelay(1);
++ evq_state = evq_info->evq_state;
++ } while ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)));
++}
++EXPORT_SYMBOL(efrm_eventq_kill_callback);
++
++static void
++efrm_eventq_do_callback(struct efhw_nic *nic, unsigned instance,
++ bool is_timeout)
++{
++ void (*handler) (void *, int is_timeout, struct efhw_nic *nic);
++ void *arg;
++ struct vi_resource_evq_info *evq_info;
++ int32_t evq_state;
++ int32_t new_evq_state;
++ struct vi_resource *virs;
++ int bit;
++
++ EFRM_TRACE("%s: q=%d %s", __FUNCTION__, instance,
++ is_timeout ? "timeout" : "wakeup");
++ EFRM_ASSERT(efrm_vi_manager);
++
++ evq_info = &efrm_vi_manager->evq_infos[instance];
++
++ /* Set the BUSY bit and clear WAKEUP_PENDING. Do this
++ * before waking up the sleeper to avoid races. */
++ while (1) {
++ evq_state = evq_info->evq_state;
++ new_evq_state = evq_state;
++
++ if ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)) != 0) {
++ EFRM_ERR("%s:%d: evq_state[%d] corrupted!",
++ __FUNCTION__, __LINE__, instance);
++ return;
++ }
++
++ if (!is_timeout)
++ new_evq_state &= ~VI_RESOURCE_EVQ_STATE(WAKEUP_PENDING);
++
++ if (evq_state & VI_RESOURCE_EVQ_STATE(CALLBACK_REGISTERED)) {
++ new_evq_state |= VI_RESOURCE_EVQ_STATE(BUSY);
++ if (cmpxchg(&evq_info->evq_state, evq_state,
++ new_evq_state) == evq_state) {
++ virs = evq_info->evq_virs;
++ break;
++ }
++
++ } else {
++ /* Just update the state if necessary. */
++ if (new_evq_state == evq_state ||
++ cmpxchg(&evq_info->evq_state, evq_state,
++ new_evq_state) == evq_state)
++ return;
++ }
++
++ udelay(1);
++ }
++
++ /* Call the callback if any. */
++ if (evq_state & VI_RESOURCE_EVQ_STATE(CALLBACK_REGISTERED)) {
++ /* Retrieve the callback fn. */
++ handler = virs->evq_callback_fn;
++ arg = virs->evq_callback_arg;
++ if (handler != NULL) /* avoid races */
++ handler(arg, is_timeout, nic);
++ }
++
++ /* Clear the BUSY bit. */
++ bit =
++ test_and_clear_bit(VI_RESOURCE_EVQ_STATE_BUSY,
++ &evq_info->evq_state);
++ if (!bit) {
++ EFRM_ERR("%s:%d: evq_state corrupted!",
++ __FUNCTION__, __LINE__);
++ }
++}
++
++void efrm_handle_wakeup_event(struct efhw_nic *nic, efhw_event_t *ev)
++{
++ efrm_eventq_do_callback(nic,
++ (unsigned int)FALCON_EVENT_WAKE_EVQ_ID(ev),
++ false);
++}
++
++void efrm_handle_timeout_event(struct efhw_nic *nic, efhw_event_t *ev)
++{
++ efrm_eventq_do_callback(nic,
++ (unsigned int)FALCON_EVENT_WAKE_EVQ_ID(ev),
++ true);
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/vi_resource_flush.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/vi_resource_flush.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/vi_resource_flush.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/vi_resource_flush.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,506 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains DMA queue flushing of VI resources.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/nic_table.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efhw/falcon.h>
++#include <ci/efrm/private.h>
++#include <ci/efrm/sysdep.h>
++#include <ci/efrm/buffer_table.h>
++#include <ci/efrm/vi_resource_private.h>
++
++#if EFRM_VI_USE_WORKQUEUE
++ /* can fail as workitem can already be scheuled -- ignore failure */
++#define EFRM_VI_RM_DELAYED_FREE(manager) \
++ queue_work(manager->workqueue, &manager->work_item)
++#else
++#define EFRM_VI_RM_DELAYED_FREE(manager) \
++ efrm_vi_rm_delayed_free(&manager->work_item)
++#endif
++
++static const int flush_fifo_hwm = 8 /* TODO should be a HW specific const */ ;
++
++static void
++efrm_vi_resource_rx_flush_done(struct vi_resource *virs, int nic_i,
++ bool *completed)
++{
++ /* We should only get a flush event if there is a flush
++ * outstanding. */
++ EFRM_ASSERT(efrm_nic_set_read
++ (&virs->rx_flush_outstanding_nic_set, nic_i));
++
++ efrm_nic_set_write(&virs->rx_flush_outstanding_nic_set, nic_i, false);
++ efrm_nic_set_write(&virs->rx_flush_nic_set, nic_i, false);
++
++ if (efrm_nic_set_is_all_clear(&virs->rx_flush_outstanding_nic_set)) {
++ list_del(&virs->rx_flush_link);
++ efrm_vi_manager->rx_flush_outstanding_count--;
++
++ if (efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set)) {
++ list_add_tail(&virs->rx_flush_link,
++ &efrm_vi_manager->close_pending);
++ *completed = 1;
++ }
++ }
++}
++
++static void
++efrm_vi_resource_tx_flush_done(struct vi_resource *virs, int nic_i,
++ bool *completed)
++{
++ /* We should only get a flush event if there is a flush
++ * outstanding. */
++ EFRM_ASSERT(efrm_nic_set_read(&virs->tx_flush_nic_set, nic_i));
++
++ efrm_nic_set_write(&virs->tx_flush_nic_set, nic_i, false);
++
++ if (efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set)) {
++ list_del(&virs->tx_flush_link);
++
++ if (efrm_nic_set_is_all_clear(&virs->rx_flush_nic_set)) {
++ list_add_tail(&virs->rx_flush_link,
++ &efrm_vi_manager->close_pending);
++ *completed = 1;
++ }
++ }
++}
++
++static void
++efrm_vi_resource_issue_rx_flush(struct vi_resource *virs, bool *completed)
++{
++ struct efhw_nic *nic;
++ int nic_i;
++ int instance;
++ int rc;
++
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++ list_add_tail(&virs->rx_flush_link,
++ &efrm_vi_manager->rx_flush_outstanding_list);
++ virs->rx_flush_outstanding_nic_set = virs->rx_flush_nic_set;
++ efrm_vi_manager->rx_flush_outstanding_count++;
++
++ EFRM_FOR_EACH_NIC_IN_SET(&virs->nic_set, nic_i, nic) {
++ EFRM_TRACE("%s: rx queue %d flush requested for nic %d",
++ __FUNCTION__, instance, nic->index);
++ rc = efhw_nic_flush_rx_dma_channel(nic, instance);
++ if (rc == -EAGAIN)
++ efrm_vi_resource_rx_flush_done(virs, nic_i, completed);
++ }
++}
++
++static void
++efrm_vi_resource_issue_tx_flush(struct vi_resource *virs, bool *completed)
++{
++ struct efhw_nic *nic;
++ int nic_i;
++ int instance;
++ int rc;
++
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++ list_add_tail(&virs->tx_flush_link,
++ &efrm_vi_manager->tx_flush_outstanding_list);
++
++ EFRM_FOR_EACH_NIC_IN_SET(&virs->nic_set, nic_i, nic) {
++ EFRM_TRACE("%s: tx queue %d flush requested for nic %d",
++ __FUNCTION__, instance, nic->index);
++ rc = efhw_nic_flush_tx_dma_channel(nic, instance);
++ if (rc == -EAGAIN)
++ efrm_vi_resource_tx_flush_done(virs, nic_i, completed);
++ }
++}
++
++static void efrm_vi_resource_process_waiting_flushes(bool *completed)
++{
++ struct vi_resource *virs;
++
++ while (efrm_vi_manager->rx_flush_outstanding_count < flush_fifo_hwm &&
++ !list_empty(&efrm_vi_manager->rx_flush_waiting_list)) {
++ virs =
++ list_entry(list_pop
++ (&efrm_vi_manager->rx_flush_waiting_list),
++ struct vi_resource, rx_flush_link);
++ efrm_vi_resource_issue_rx_flush(virs, completed);
++ }
++}
++
++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
++static void
++efrm_vi_resource_flush_retry_vi(struct vi_resource *virs,
++ int64_t time_now, bool *completed)
++{
++ struct efhw_nic *nic;
++ int nic_i;
++ int instance;
++
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++ virs->flush_count++;
++ virs->flush_time = time_now;
++
++#if BUG7916_WORKAROUND
++ if (!efrm_nic_set_is_all_clear(&virs->rx_flush_outstanding_nic_set)) {
++ EFRM_TRACE("%s: Retrying RX flush on instance %d",
++ __FUNCTION__, instance);
++
++ list_del(&virs->rx_flush_link);
++ efrm_vi_manager->rx_flush_outstanding_count--;
++ efrm_vi_resource_issue_rx_flush(virs, completed);
++ efrm_vi_resource_process_waiting_flushes(completed);
++ }
++#endif
++
++#if BUG5302_WORKAROUND
++ if (!efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set)) {
++ if (virs->flush_count > 5) {
++ EFRM_TRACE("%s: VI resource stuck flush pending "
++ "(instance=%d, count=%d)",
++ __FUNCTION__, instance, virs->flush_count);
++ EFRM_FOR_EACH_NIC_IN_SET(&virs->tx_flush_nic_set,
++ nic_i, nic) {
++ falcon_clobber_tx_dma_ptrs(nic, instance);
++ }
++ } else {
++ EFRM_TRACE("%s: Retrying TX flush on instance %d",
++ __FUNCTION__, instance);
++ }
++
++ list_del(&virs->tx_flush_link);
++ efrm_vi_resource_issue_tx_flush(virs, completed);
++ }
++#endif
++}
++#endif
++
++int efrm_vi_resource_flush_retry(struct vi_resource *virs)
++{
++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
++ irq_flags_t lock_flags;
++ bool completed = false;
++
++ if (efrm_nic_set_is_all_clear(&virs->rx_flush_nic_set) &&
++ efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set))
++ return -EALREADY;
++
++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
++ efrm_vi_resource_flush_retry_vi(virs, get_jiffies_64(), &completed);
++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ if (completed)
++ EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager);
++#endif
++
++ return 0;
++}
++EXPORT_SYMBOL(efrm_vi_resource_flush_retry);
++
++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
++/* resource manager lock should be taken before this call */
++static void efrm_vi_handle_flush_loss(bool *completed)
++{
++ struct list_head *pos, *temp;
++ struct vi_resource *virs;
++ int64_t time_now, time_pending;
++
++ /* It's possible we miss flushes - the list is sorted in order we
++ * generate flushes, see if any are very old. It's also possible
++ * that we decide an endpoint is flushed even though we've not
++ * received all the flush events. We *should * mark as
++ * completed, reclaim and loop again. ??
++ * THIS NEEDS BACKPORTING FROM THE FALCON branch
++ */
++ time_now = get_jiffies_64();
++
++#if BUG7916_WORKAROUND
++ list_for_each_safe(pos, temp,
++ &efrm_vi_manager->rx_flush_outstanding_list) {
++ virs = container_of(pos, struct vi_resource, rx_flush_link);
++
++ time_pending = time_now - virs->flush_time;
++
++ /* List entries are held in reverse chronological order. Only
++ * process the old ones. */
++ if (time_pending <= 0x100000000LL)
++ break;
++
++ efrm_vi_resource_flush_retry_vi(virs, time_now, completed);
++ }
++#endif
++
++#if BUG5302_WORKAROUND
++ list_for_each_safe(pos, temp,
++ &efrm_vi_manager->tx_flush_outstanding_list) {
++ virs = container_of(pos, struct vi_resource, tx_flush_link);
++
++ time_pending = time_now - virs->flush_time;
++
++ /* List entries are held in reverse chronological order.
++ * Only process the old ones. */
++ if (time_pending <= 0x100000000LL)
++ break;
++
++ efrm_vi_resource_flush_retry_vi(virs, time_now, completed);
++ }
++#endif
++}
++#endif
++
++void
++efrm_vi_register_flush_callback(struct vi_resource *virs,
++ void (*handler)(void *), void *arg)
++{
++ if (handler == NULL) {
++ virs->flush_callback_fn = handler;
++ wmb();
++ virs->flush_callback_arg = arg;
++ } else {
++ virs->flush_callback_arg = arg;
++ wmb();
++ virs->flush_callback_fn = handler;
++ }
++}
++EXPORT_SYMBOL(efrm_vi_register_flush_callback);
++
++int efrm_pt_flush(struct vi_resource *virs)
++{
++ int instance;
++ irq_flags_t lock_flags;
++ bool completed = false;
++
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++ EFRM_ASSERT(efrm_nic_set_is_all_clear(&virs->rx_flush_nic_set));
++ EFRM_ASSERT(efrm_nic_set_is_all_clear
++ (&virs->rx_flush_outstanding_nic_set));
++ EFRM_ASSERT(efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set));
++
++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " EVQ=%d TXQ=%d RXQ=%d",
++ __FUNCTION__, EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
++ virs->evq_capacity,
++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX],
++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]);
++
++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] != 0)
++ virs->rx_flush_nic_set = virs->nic_set;
++
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] != 0)
++ virs->tx_flush_nic_set = virs->nic_set;
++
++ /* Clean up immediately if there are no flushes. */
++ if (efrm_nic_set_is_all_clear(&virs->rx_flush_nic_set) &&
++ efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set)) {
++ list_add_tail(&virs->rx_flush_link,
++ &efrm_vi_manager->close_pending);
++ completed = true;
++ }
++
++ /* Issue the RX flush if possible or queue it for later. */
++ if (!efrm_nic_set_is_all_clear(&virs->rx_flush_nic_set)) {
++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
++ if (efrm_vi_manager->rx_flush_outstanding_count >=
++ flush_fifo_hwm)
++ efrm_vi_handle_flush_loss(&completed);
++#endif
++ if (efrm_vi_manager->rx_flush_outstanding_count >=
++ flush_fifo_hwm) {
++ list_add_tail(&virs->rx_flush_link,
++ &efrm_vi_manager->rx_flush_waiting_list);
++ } else {
++ efrm_vi_resource_issue_rx_flush(virs, &completed);
++ }
++ }
++
++ /* Issue the TX flush. There's no limit to the number of
++ * outstanding TX flushes. */
++ if (!efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set))
++ efrm_vi_resource_issue_tx_flush(virs, &completed);
++
++ virs->flush_time = get_jiffies_64();
++
++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ if (completed)
++ EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager);
++
++ return 0;
++}
++EXPORT_SYMBOL(efrm_pt_flush);
++
++static void
++efrm_handle_rx_dmaq_flushed(struct efhw_nic *flush_nic, int instance,
++ bool *completed)
++{
++ struct list_head *pos, *temp;
++ struct vi_resource *virs;
++
++ list_for_each_safe(pos, temp,
++ &efrm_vi_manager->rx_flush_outstanding_list) {
++ virs = container_of(pos, struct vi_resource, rx_flush_link);
++
++ if (instance == EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)) {
++ efrm_vi_resource_rx_flush_done(virs,
++ flush_nic->index,
++ completed);
++ efrm_vi_resource_process_waiting_flushes(completed);
++ return;
++ }
++ }
++ EFRM_TRACE("%s: Unhandled rx flush event, nic %d, instance %d",
++ __FUNCTION__, flush_nic->index, instance);
++}
++
++static void
++efrm_handle_tx_dmaq_flushed(struct efhw_nic *flush_nic, int instance,
++ bool *completed)
++{
++ struct list_head *pos, *temp;
++ struct vi_resource *virs;
++
++ list_for_each_safe(pos, temp,
++ &efrm_vi_manager->tx_flush_outstanding_list) {
++ virs = container_of(pos, struct vi_resource, tx_flush_link);
++
++ if (instance == EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)) {
++ efrm_vi_resource_tx_flush_done(virs,
++ flush_nic->index,
++ completed);
++ return;
++ }
++ }
++ EFRM_TRACE("%s: Unhandled tx flush event, nic %d, instance %d",
++ __FUNCTION__, flush_nic->index, instance);
++}
++
++void
++efrm_handle_dmaq_flushed(struct efhw_nic *flush_nic, int instance,
++ int rx_flush)
++{
++ irq_flags_t lock_flags;
++ bool completed = false;
++
++ EFRM_TRACE("%s: nic_i=%d instance=%d rx_flush=%d", __FUNCTION__,
++ flush_nic->index, instance, rx_flush);
++
++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ if (rx_flush)
++ efrm_handle_rx_dmaq_flushed(flush_nic, instance, &completed);
++ else
++ efrm_handle_tx_dmaq_flushed(flush_nic, instance, &completed);
++
++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
++ efrm_vi_handle_flush_loss(&completed);
++#endif
++
++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ if (completed)
++ EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager);
++}
++
++static void
++efrm_vi_rm_reinit_dmaqs(struct vi_resource *virs)
++{
++ struct efhw_nic *nic;
++ int nic_i;
++
++ EFRM_FOR_EACH_NIC_IN_SET(&virs->nic_set, nic_i, nic) {
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] != 0)
++ efrm_vi_rm_init_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
++ nic);
++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX])
++ efrm_vi_rm_init_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
++ nic);
++ }
++}
++
++/* free any PT endpoints whose flush has now complete */
++void efrm_vi_rm_delayed_free(struct work_struct *data)
++{
++ irq_flags_t lock_flags;
++ struct list_head close_pending;
++ struct vi_resource *virs;
++
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_vi_manager->rm);
++
++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
++ list_replace_init(&efrm_vi_manager->close_pending, &close_pending);
++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ EFRM_TRACE("%s: %p", __FUNCTION__, efrm_vi_manager);
++ while (!list_empty(&close_pending)) {
++ virs =
++ list_entry(list_pop(&close_pending), struct vi_resource,
++ rx_flush_link);
++ EFRM_TRACE("%s: flushed VI instance=%d", __FUNCTION__,
++ EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle));
++
++ if (virs->flush_callback_fn != NULL) {
++ efrm_vi_rm_reinit_dmaqs(virs);
++ virs->flush_callback_fn(virs->flush_callback_arg);
++ } else
++ efrm_vi_rm_free_flushed_resource(virs);
++ }
++}
++
++void efrm_vi_rm_salvage_flushed_vis(void)
++{
++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
++ irq_flags_t lock_flags;
++ bool completed;
++
++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
++ efrm_vi_handle_flush_loss(&completed);
++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
++#endif
++
++ efrm_vi_rm_delayed_free(&efrm_vi_manager->work_item);
++}
++
++void efrm_vi_resource_free(struct vi_resource *virs)
++{
++ efrm_vi_register_flush_callback(virs, NULL, NULL);
++ efrm_pt_flush(virs);
++}
++EXPORT_SYMBOL(efrm_vi_resource_free);
++
++/*
++ * vi: sw=8:ai:aw
++ */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfc_resource/vi_resource_manager.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/vi_resource_manager.c
+--- linux-2.6.18.8/drivers/net/sfc/sfc_resource/vi_resource_manager.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfc_resource/vi_resource_manager.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,259 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains the VI resource manager.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/nic_table.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efhw/falcon.h>
++#include <ci/efrm/private.h>
++#include <ci/efrm/vi_resource_private.h>
++
++int efrm_pt_pace(struct vi_resource *virs, unsigned int val)
++{
++#if defined(__CI_HARDWARE_CONFIG_FALCON__)
++ int instance, nic_i;
++ struct efhw_nic *nic;
++
++ EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++ EFRM_FOR_EACH_NIC_IN_SET(&virs->nic_set, nic_i, nic)
++ falcon_nic_pace(nic, instance, val);
++
++ EFRM_TRACE("%s[%d]=%d DONE", __FUNCTION__, instance, val);
++ return 0;
++#else
++ return -EOPNOTSUPP;
++#endif
++}
++EXPORT_SYMBOL(efrm_pt_pace);
++
++/*** Resource manager creation/destruction *******************************/
++
++static void efrm_vi_rm_dtor(struct efrm_resource_manager *rm);
++
++static int
++efrm_create_or_destroy_vi_resource_manager(
++ struct efrm_resource_manager **rm_in_out,
++ const struct vi_resource_dimensions *dims,
++ bool destroy)
++{
++ struct vi_resource *virs;
++ struct list_head *pos, *temp;
++ struct list_head flush_pending;
++ irq_flags_t lock_flags;
++ int rc, i, n_evqs;
++ unsigned dmaq_min, dmaq_max;
++
++ EFRM_ASSERT(rm_in_out);
++
++ if (destroy)
++ goto destroy;
++
++ EFRM_ASSERT(dims);
++ EFRM_NOTICE("vi_resource_manager: evq_int=%u-%u evq_timer=%u-%u",
++ dims->evq_int_min, dims->evq_int_max,
++ dims->evq_timer_min, dims->evq_timer_max);
++ EFRM_NOTICE("vi_resource_manager: rxq=%u-%u txq=%u-%u",
++ dims->rxq_min, dims->rxq_max,
++ dims->txq_min, dims->txq_max);
++
++ efrm_vi_manager = kmalloc(sizeof(*efrm_vi_manager), GFP_KERNEL);
++ if (efrm_vi_manager == NULL) {
++ rc = -ENOMEM;
++ goto fail_alloc;
++ }
++
++ memset(efrm_vi_manager, 0, sizeof(*efrm_vi_manager));
++
++ efrm_vi_manager->iscsi_dmaq_instance_is_free = true;
++
++ dmaq_min = max(dims->rxq_min, dims->txq_min);
++ dmaq_max = min(dims->rxq_max, dims->txq_max);
++
++ efrm_vi_manager->with_timer_base =
++ max(dmaq_min, dims->evq_timer_min);
++ efrm_vi_manager->with_timer_limit =
++ min(dmaq_max, dims->evq_timer_max);
++ rc = efrm_kfifo_id_ctor(&efrm_vi_manager->instances_with_timer,
++ efrm_vi_manager->with_timer_base,
++ efrm_vi_manager->with_timer_limit,
++ &efrm_vi_manager->rm.rm_lock);
++ if (rc < 0)
++ goto fail_with_timer_id_pool;
++
++ efrm_vi_manager->with_interrupt_base =
++ max(dmaq_min, dims->evq_int_min);
++ efrm_vi_manager->with_interrupt_limit =
++ min(dmaq_max, dims->evq_int_max);
++ efrm_vi_manager->with_interrupt_limit =
++ max(efrm_vi_manager->with_interrupt_limit,
++ efrm_vi_manager->with_interrupt_base);
++ rc = efrm_kfifo_id_ctor(&efrm_vi_manager->instances_with_interrupt,
++ efrm_vi_manager->with_interrupt_base,
++ efrm_vi_manager->with_interrupt_limit,
++ &efrm_vi_manager->rm.rm_lock);
++ if (rc < 0)
++ goto fail_with_int_id_pool;
++
++ n_evqs = max(efrm_vi_manager->with_timer_limit,
++ efrm_vi_manager->with_interrupt_limit);
++ rc = -ENOMEM;
++ efrm_vi_manager->evq_infos =
++ vmalloc(n_evqs * sizeof(struct vi_resource_evq_info));
++ if (efrm_vi_manager->evq_infos == NULL)
++ goto fail_alloc_evq_infos;
++
++ for (i = 0; i < n_evqs; ++i) {
++ efrm_vi_manager->evq_infos[i].evq_state = 0;
++ efrm_vi_manager->evq_infos[i].evq_virs = NULL;
++ }
++
++ INIT_LIST_HEAD(&efrm_vi_manager->rx_flush_waiting_list);
++ INIT_LIST_HEAD(&efrm_vi_manager->rx_flush_outstanding_list);
++ INIT_LIST_HEAD(&efrm_vi_manager->tx_flush_outstanding_list);
++ efrm_vi_manager->rx_flush_outstanding_count = 0;
++
++ INIT_LIST_HEAD(&efrm_vi_manager->close_pending);
++#if EFRM_VI_USE_WORKQUEUE
++ efrm_vi_manager->workqueue = create_workqueue("sfc_vi");
++ if (efrm_vi_manager->workqueue == NULL)
++ goto fail_create_workqueue;
++#endif
++ INIT_WORK(&efrm_vi_manager->work_item, efrm_vi_rm_delayed_free);
++
++ /* NB. This must be the last step to avoid things getting tangled.
++ * efrm_resource_manager_dtor calls the vi_rm_dtor which ends up in
++ * this function. */
++ rc = efrm_resource_manager_ctor(&efrm_vi_manager->rm, efrm_vi_rm_dtor,
++ "VI", EFRM_RESOURCE_VI, 0);
++ if (rc < 0)
++ goto fail_rm_ctor;
++
++ *rm_in_out = &efrm_vi_manager->rm;
++ return 0;
++
++destroy:
++ rc = 0;
++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(*rm_in_out);
++
++ /* Abort outstanding flushes. Note, a VI resource can be on more
++ * than one of these lists. We handle this by starting with the TX
++ * list and then append VIs to this list if they aren't on the TX
++ * list already. A VI is on the TX flush list if tx_flush_nic_set
++ * is not empty. */
++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ list_replace_init(&efrm_vi_manager->tx_flush_outstanding_list,
++ &flush_pending);
++
++ list_for_each_safe(pos, temp,
++ &efrm_vi_manager->rx_flush_waiting_list) {
++ virs = container_of(pos, struct vi_resource, rx_flush_link);
++
++ list_del(&virs->rx_flush_link);
++ if (efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set))
++ list_add_tail(&virs->tx_flush_link, &flush_pending);
++ }
++
++ list_for_each_safe(pos, temp,
++ &efrm_vi_manager->rx_flush_outstanding_list) {
++ virs = container_of(pos, struct vi_resource, rx_flush_link);
++
++ list_del(&virs->rx_flush_link);
++ if (efrm_nic_set_is_all_clear(&virs->tx_flush_nic_set))
++ list_add_tail(&virs->tx_flush_link, &flush_pending);
++ }
++
++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
++
++ while (!list_empty(&flush_pending)) {
++ virs =
++ list_entry(list_pop(&flush_pending), struct vi_resource,
++ tx_flush_link);
++ EFRM_TRACE("%s: found PT endpoint " EFRM_RESOURCE_FMT
++ " with flush pending [Tx=0x%x, Rx=0x%x, RxO=0x%x]",
++ __FUNCTION__,
++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
++ virs->tx_flush_nic_set.nics,
++ virs->rx_flush_nic_set.nics,
++ virs->rx_flush_outstanding_nic_set.nics);
++ efrm_vi_rm_free_flushed_resource(virs);
++ }
++
++fail_rm_ctor:
++
++ /* Complete outstanding closes. */
++#if EFRM_VI_USE_WORKQUEUE
++ destroy_workqueue(efrm_vi_manager->workqueue);
++fail_create_workqueue:
++#endif
++ EFRM_ASSERT(list_empty(&efrm_vi_manager->close_pending));
++
++ n_evqs = max(efrm_vi_manager->with_timer_limit,
++ efrm_vi_manager->with_interrupt_limit);
++ vfree(efrm_vi_manager->evq_infos);
++fail_alloc_evq_infos:
++
++ kfifo_vfree(efrm_vi_manager->instances_with_interrupt);
++fail_with_int_id_pool:
++
++ kfifo_vfree(efrm_vi_manager->instances_with_timer);
++fail_with_timer_id_pool:
++
++ if (destroy)
++ return 0;
++
++ EFRM_DO_DEBUG(memset(efrm_vi_manager, 0, sizeof(*efrm_vi_manager)));
++ kfree(efrm_vi_manager);
++fail_alloc:
++
++ *rm_in_out = NULL;
++ EFRM_ERR("%s: failed rc=%d", __FUNCTION__, rc);
++ return rc;
++}
++
++int
++efrm_create_vi_resource_manager(struct efrm_resource_manager **rm_out,
++ const struct vi_resource_dimensions *dims)
++{
++ return efrm_create_or_destroy_vi_resource_manager(rm_out, dims, false);
++}
++
++static void efrm_vi_rm_dtor(struct efrm_resource_manager *rm)
++{
++ efrm_create_or_destroy_vi_resource_manager(&rm, NULL, true);
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/sfe4001.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfe4001.c
+--- linux-2.6.18.8/drivers/net/sfc/sfe4001.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/sfe4001.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,315 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************/
++
++/*****************************************************************************
++ * Support for the SFE4001 NIC: driver code for the PCA9539 I/O expander that
++ * controls the PHY power rails, and for the MAX6647 temp. sensor used to check
++ * the PHY
++ */
++#include <linux/delay.h>
++#include "efx.h"
++#include "phy.h"
++#include "boards.h"
++#include "falcon.h"
++#include "falcon_hwdefs.h"
++
++/**************************************************************************
++ *
++ * I2C IO Expander device
++ *
++ **************************************************************************/
++#define PCA9539 0x74
++
++#define P0_IN 0x00
++#define P0_OUT 0x02
++#define P0_INVERT 0x04
++#define P0_CONFIG 0x06
++
++#define P0_EN_1V0X_LBN 0
++#define P0_EN_1V0X_WIDTH 1
++#define P0_EN_1V2_LBN 1
++#define P0_EN_1V2_WIDTH 1
++#define P0_EN_2V5_LBN 2
++#define P0_EN_2V5_WIDTH 1
++#define P0_EN_3V3X_LBN 3
++#define P0_EN_3V3X_WIDTH 1
++#define P0_EN_5V_LBN 4
++#define P0_EN_5V_WIDTH 1
++#define P0_SHORTEN_JTAG_LBN 5
++#define P0_SHORTEN_JTAG_WIDTH 1
++#define P0_X_TRST_LBN 6
++#define P0_X_TRST_WIDTH 1
++#define P0_DSP_RESET_LBN 7
++#define P0_DSP_RESET_WIDTH 1
++
++#define P1_IN 0x01
++#define P1_OUT 0x03
++#define P1_INVERT 0x05
++#define P1_CONFIG 0x07
++
++#define P1_AFE_PWD_LBN 0
++#define P1_AFE_PWD_WIDTH 1
++#define P1_DSP_PWD25_LBN 1
++#define P1_DSP_PWD25_WIDTH 1
++#define P1_RESERVED_LBN 2
++#define P1_RESERVED_WIDTH 2
++#define P1_SPARE_LBN 4
++#define P1_SPARE_WIDTH 4
++
++
++/**************************************************************************
++ *
++ * Temperature Sensor
++ *
++ **************************************************************************/
++#define MAX6647 0x4e
++
++#define RLTS 0x00
++#define RLTE 0x01
++#define RSL 0x02
++#define RCL 0x03
++#define RCRA 0x04
++#define RLHN 0x05
++#define RLLI 0x06
++#define RRHI 0x07
++#define RRLS 0x08
++#define WCRW 0x0a
++#define WLHO 0x0b
++#define WRHA 0x0c
++#define WRLN 0x0e
++#define OSHT 0x0f
++#define REET 0x10
++#define RIET 0x11
++#define RWOE 0x19
++#define RWOI 0x20
++#define HYS 0x21
++#define QUEUE 0x22
++#define MFID 0xfe
++#define REVID 0xff
++
++/* Status bits */
++#define MAX6647_BUSY (1 << 7) /* ADC is converting */
++#define MAX6647_LHIGH (1 << 6) /* Local high temp. alarm */
++#define MAX6647_LLOW (1 << 5) /* Local low temp. alarm */
++#define MAX6647_RHIGH (1 << 4) /* Remote high temp. alarm */
++#define MAX6647_RLOW (1 << 3) /* Remote low temp. alarm */
++#define MAX6647_FAULT (1 << 2) /* DXN/DXP short/open circuit */
++#define MAX6647_EOT (1 << 1) /* Remote junction overtemp. */
++#define MAX6647_IOT (1 << 0) /* Local junction overtemp. */
++
++static const u8 xgphy_max_temperature = 90;
++
++void sfe4001_poweroff(struct efx_nic *efx)
++{
++ struct efx_i2c_interface *i2c = &efx->i2c;
++
++ u8 cfg, out, in;
++
++ EFX_INFO(efx, "%s\n", __func__);
++
++ /* Turn off all power rails */
++ out = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P0_OUT, &out, EFX_BYTE);
++
++ /* Disable port 1 outputs on IO expander */
++ cfg = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, EFX_BYTE);
++
++ /* Disable port 0 outputs on IO expander */
++ cfg = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, EFX_BYTE);
++
++ /* Clear any over-temperature alert */
++ (void) efx_i2c_read(i2c, MAX6647, RSL, &in, EFX_BYTE);
++}
++
++static int sfe4001_check_hw(struct efx_nic *efx)
++{
++ struct efx_i2c_interface *i2c = &efx->i2c;
++ int rc;
++ u8 status;
++
++ /* Check the powered status of the PHY. Lack of power implies that
++ * the MAX6647 has shut down power to it, probably due to a temp.
++ * alarm. Reading the power status rather than the MAX6647 status
++ * directly because the later is read-to-clear and would thus
++ * start to power up the PHY again when polled, causing us to blip
++ * the power undesirably */
++
++ /* If XAUI link is down, check power status. Reading
++ * power requires a I2C byte read, which is too slow
++ * to poll (see SFC bug 7884). */
++ if (falcon_xaui_link_ok(efx))
++ return 0;
++
++ rc = efx_i2c_read(i2c, PCA9539, P1_IN, &status, EFX_BYTE);
++ status &= ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN));
++
++ /* We know we can read from the IO expander because we did
++ * it during power-on. Assume failure now is bad news. */
++ if (rc != 0 || status == 0) {
++ sfe4001_poweroff(efx);
++
++ /* Note that the PHY is pining for the cooling fans */
++ tenxpress_set_state(efx, TENXPRESS_STATUS_OTEMP);
++
++ /* Log the info */
++ if (status == 0) {
++ EFX_ERR(efx, "%s: Temperature sensor reports "
++ "alarm! (0x%x) Shutting down PHY.\n",
++ __func__, status);
++ rc = -EIO;
++ } else {
++ EFX_ERR(efx, "%s: Failed to read PHY status!"
++ " Shutting down PHY.\n",
++ __func__);
++ }
++ }
++
++ return rc;
++}
++
++/* This board uses an I2C expander to provider power to the PHY, which needs to
++ * be turned on before the PHY can be used.
++ * Context: Process context, rtnl lock held
++ */
++int sfe4001_poweron(struct efx_nic *efx)
++{
++ struct efx_i2c_interface *i2c = &efx->i2c;
++ unsigned int count;
++ int rc;
++ u8 out, in, cfg;
++ efx_dword_t reg;
++
++ /* 10Xpress has fixed-function LED pins, so there is no board-specific
++ * blink code. */
++ efx->board_info.blink = tenxpress_phy_blink;
++
++ /* Ensure that XGXS and XAUI SerDes are held in reset */
++ EFX_POPULATE_DWORD_7(reg, XX_PWRDNA_EN, 1,
++ XX_PWRDNB_EN, 1,
++ XX_RSTPLLAB_EN, 1,
++ XX_RESETA_EN, 1,
++ XX_RESETB_EN, 1,
++ XX_RSTXGXSRX_EN, 1,
++ XX_RSTXGXSTX_EN, 1);
++ efx->mac_op->mac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
++ udelay(10);
++
++ efx->board_info.monitor = sfe4001_check_hw;
++ efx->board_info.fini = sfe4001_poweroff;
++
++ /* Set DSP over-temperature alert threshold */
++ EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature);
++ rc = efx_i2c_write(i2c, MAX6647, WLHO,
++ &xgphy_max_temperature, EFX_BYTE);
++ if (rc)
++ goto fail1;
++
++ /* Read it back and verify */
++ rc = efx_i2c_read(i2c, MAX6647, RLHN, &in, EFX_BYTE);
++ if (rc)
++ goto fail1;
++ if (in != xgphy_max_temperature) {
++ rc = -EFAULT;
++ goto fail1;
++ }
++
++ /* Clear any previous over-temperature alert */
++ rc = efx_i2c_read(i2c, MAX6647, RSL, &in, EFX_BYTE);
++ if (rc)
++ goto fail1;
++
++ /* Enable port 0 and port 1 outputs on IO expander */
++ cfg = 0x00;
++ rc = efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, EFX_BYTE);
++ if (rc)
++ goto fail1;
++ cfg = 0xff & ~(1 << P1_SPARE_LBN);
++ rc = efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, EFX_BYTE);
++ if (rc)
++ goto fail2;
++
++ /* Turn all power off then wait 1 sec. This ensures PHY is reset */
++ out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
++ (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
++ (0 << P0_EN_1V0X_LBN));
++ rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, EFX_BYTE);
++ if (rc)
++ goto fail3;
++
++ schedule_timeout_uninterruptible(HZ);
++ count = 0;
++ do {
++ /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
++ out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
++ (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
++ (1 << P0_X_TRST_LBN));
++
++ rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, EFX_BYTE);
++ if (rc)
++ goto fail3;
++ msleep(10);
++
++ /* Turn on 1V power rail */
++ out &= ~(1 << P0_EN_1V0X_LBN);
++ rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, EFX_BYTE);
++ if (rc)
++ goto fail3;
++
++ EFX_INFO(efx, "waiting for power (attempt %d)...\n", count);
++
++ schedule_timeout_uninterruptible(HZ);
++
++ /* Check DSP is powered */
++ rc = efx_i2c_read(i2c, PCA9539, P1_IN, &in, EFX_BYTE);
++ if (rc)
++ goto fail3;
++ if (in & (1 << P1_AFE_PWD_LBN))
++ goto done;
++
++ } while (++count < 20);
++
++ EFX_INFO(efx, "timed out waiting for power\n");
++ rc = -ETIMEDOUT;
++ goto fail3;
++
++done:
++ EFX_INFO(efx, "PHY is powered on\n");
++ return 0;
++
++fail3:
++ /* Turn off all power rails */
++ out = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P0_OUT, &out, EFX_BYTE);
++ /* Disable port 1 outputs on IO expander */
++ out = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &out, EFX_BYTE);
++fail2:
++ /* Disable port 0 outputs on IO expander */
++ out = 0xff;
++ (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &out, EFX_BYTE);
++fail1:
++ return rc;
++}
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/spi.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/spi.h
+--- linux-2.6.18.8/drivers/net/sfc/spi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/spi.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,186 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005: Fen Systems Ltd.
++ * Copyright 2006: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_SPI_H
++#define EFX_SPI_H
++
++#include "net_driver.h"
++
++/**************************************************************************
++ *
++ * Basic SPI command set and bit definitions
++ *
++ *************************************************************************/
++
++/*
++ * Commands common to all known devices.
++ *
++ */
++
++/* Write status register */
++#define SPI_WRSR 0x01
++
++/* Write data to memory array */
++#define SPI_WRITE 0x02
++
++/* Read data from memory array */
++#define SPI_READ 0x03
++
++/* Reset write enable latch */
++#define SPI_WRDI 0x04
++
++/* Read status register */
++#define SPI_RDSR 0x05
++
++/* Set write enable latch */
++#define SPI_WREN 0x06
++
++/* SST: Enable write to status register */
++#define SPI_SST_EWSR 0x50
++
++/*
++ * Status register bits. Not all bits are supported on all devices.
++ *
++ */
++
++/* Write-protect pin enabled */
++#define SPI_STATUS_WPEN 0x80
++
++/* Block protection bit 2 */
++#define SPI_STATUS_BP2 0x10
++
++/* Block protection bit 1 */
++#define SPI_STATUS_BP1 0x08
++
++/* Block protection bit 0 */
++#define SPI_STATUS_BP0 0x04
++
++/* State of the write enable latch */
++#define SPI_STATUS_WEN 0x02
++
++/* Device busy flag */
++#define SPI_STATUS_NRDY 0x01
++
++/**************************************************************************
++ *
++ * Efx SPI devices
++ *
++ **************************************************************************
++ */
++
++/**
++ * struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device
++ * @device_id: Controller's id for the device
++ * @size: Size (in bytes)
++ * @addr_len: Number of address bytes in read/write commands
++ * @munge_address: Flag whether addresses should be munged.
++ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM)
++ * use bit 3 of the command byte as address bit A8, rather
++ * than having a two-byte address. If this flag is set, then
++ * commands should be munged in this way.
++ * @erase_command: Erase command (or 0 if sector erase not needed).
++ * @erase_size: Erase sector size (in bytes)
++ * Erase commands affect sectors with this size and alignment.
++ * This must be a power of two.
++ * @block_size: Write block size (in bytes).
++ * Write commands are limited to blocks with this size and alignment.
++ * @read: Read function for the device
++ * @write: Write function for the device
++ */
++struct efx_spi_device {
++ int device_id;
++ unsigned int size;
++ unsigned int addr_len;
++ unsigned int munge_address:1;
++ u8 erase_command;
++ unsigned int erase_size;
++ unsigned int block_size;
++ int (*read) (const struct efx_spi_device *spi,
++ struct efx_nic *efx, unsigned int command,
++ int address, void *data, unsigned int len);
++ int (*write) (const struct efx_spi_device *spi,
++ struct efx_nic *efx, unsigned int command,
++ int address, const void *data, unsigned int len);
++};
++
++/* Maximum length for SPI read or write through Falcon */
++#define FALCON_SPI_MAX_LEN 16U
++
++/**
++ * efx_spi_write_limit - calculate maximum permitted length for write
++ * @spi: SPI device description
++ * @start: Starting address
++ *
++ * Return the maximum length for a write starting at the given address
++ * in the device.
++ *
++ * SPI writes must not cross block boundaries. Devices tend
++ * to wrap addresses at block boundaries; e.g. trying to write 5 bytes
++ * starting at offset 14 with a block size of 16 might write
++ * {14,15,0,1,2} rather than {14,15,16,17,18}.
++ */
++static inline unsigned int
++efx_spi_write_limit(const struct efx_spi_device *spi, unsigned int start)
++{
++ return min(FALCON_SPI_MAX_LEN,
++ (spi->block_size - (start & (spi->block_size - 1))));
++}
++
++/**
++ * efx_spi_read_limit - calculate maximum permitted length for read
++ * @spi: SPI device description
++ * @start: Starting address
++ *
++ * Return the maximum length for a read starting at the given address
++ * in the device.
++ */
++static inline unsigned int
++efx_spi_read_limit(const struct efx_spi_device *spi __attribute__ ((unused)),
++ unsigned int start __attribute__ ((unused)))
++{
++ return FALCON_SPI_MAX_LEN;
++}
++
++/**
++ * efx_spi_munge_command - adjust command as necessary for given address
++ * @spi: SPI device description
++ * @command: Normal SPI command
++ * @address: Address for command
++ *
++ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) use bit 3
++ * of the command byte as address bit A8, rather than having a
++ * two-byte address. This function calculates the appropriate command
++ * byte for the device, taking this munging into account.
++ */
++static inline u8 efx_spi_munge_command(const struct efx_spi_device *spi,
++ const u8 command,
++ const unsigned int address)
++{
++ return (command | (((address >> 8) & spi->munge_address) << 3));
++}
++
++#endif /* EFX_SPI_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/tenxpress.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/tenxpress.c
+--- linux-2.6.18.8/drivers/net/sfc/tenxpress.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/tenxpress.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,697 @@
++/****************************************************************************
++ * Driver for Solarflare 802.3an compliant PHY
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************/
++
++#include <linux/delay.h>
++#include <linux/seq_file.h>
++#include "efx.h"
++#include "debugfs.h"
++#include "gmii.h"
++#include "mdio_10g.h"
++#include "falcon.h"
++#include "phy.h"
++#include "falcon_hwdefs.h"
++#include "boards.h"
++
++/* We expect these MMDs to be in the package */
++/* AN not here as mdio_check_mmds() requires STAT2 support */
++#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PMAPMD | \
++ MDIO_MMDREG_DEVS0_PCS | \
++ MDIO_MMDREG_DEVS0_PHYXS)
++
++#define TENXPRESS_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \
++ (1 << LOOPBACK_PCS) | \
++ (1 << LOOPBACK_PMAPMD) | \
++ (1 << LOOPBACK_NETWORK))
++
++/* We complain if we fail to see the link partner as 10G capable this many
++ * times in a row (must be > 1 as sampling the autoneg. registers is racy)
++ */
++#define MAX_BAD_LP_TRIES (5)
++
++/* SNR operating margin register */
++#define PMA_PMD_SNR_MARGIN_0 (133)
++#define PMA_PMD_SNR_MARGIN_1 (134)
++#define PMA_PMD_SNR_MARGIN_2 (135)
++#define PMA_PMD_SNR_MARGIN_3 (136)
++
++/* Extended control register */
++#define PMA_PMD_XCONTROL_REG 0xc000
++#define PMA_PMD_LNPGA_POWERDOWN_LBN 8
++#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1
++#define PMA_PMD_AFE_POWERDOWN_LBN 9
++#define PMA_PMD_AFE_POWERDOWN_WIDTH 1
++#define PMA_PMD_DSP_POWERDOWN_LBN 10
++#define PMA_PMD_DSP_POWERDOWN_WIDTH 1
++#define PMA_PMD_PHY_POWERDOWN_LBN 11
++#define PMA_PMD_PHY_POWERDOWN_WI
++
++/* extended status register */
++#define PMA_PMD_XSTATUS_REG 0xc001
++#define PMA_PMD_XSTAT_FLP_LBN (12)
++
++
++/* LED control register */
++#define PMA_PMD_LED_CTRL_REG (0xc007)
++#define PMA_PMA_LED_ACTIVITY_LBN (3)
++
++/* LED function override register */
++#define PMA_PMD_LED_OVERR_REG (0xc009)
++/* Bit positions for different LEDs (there are more but not wired on SFE4001)*/
++#define PMA_PMD_LED_LINK_LBN (0)
++#define PMA_PMD_LED_SPEED_LBN (2)
++#define PMA_PMD_LED_TX_LBN (4)
++#define PMA_PMD_LED_RX_LBN (6)
++/* Override settings */
++#define PMA_PMD_LED_AUTO (0) /* H/W control */
++#define PMA_PMD_LED_ON (1)
++#define PMA_PMD_LED_OFF (2)
++#define PMA_PMD_LED_FLASH (3)
++/* All LEDs under hardware control */
++#define PMA_PMD_LED_FULL_AUTO (0)
++/* Green and Amber under hardware control, Red off */
++#define PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
++
++
++/* Self test (BIST) control register */
++#define PMA_PMD_BIST_CTRL_REG (0xc014)
++#define PMA_PMD_BIST_BER_LBN (2) /* Run BER test */
++#define PMA_PMD_BIST_CONT_LBN (1) /* Run continuous BIST until cleared */
++#define PMA_PMD_BIST_SINGLE_LBN (0) /* Run 1 BIST iteration (self clears) */
++/* Self test status register */
++#define PMA_PMD_BIST_STAT_REG (0xc015)
++#define PMA_PMD_BIST_ENX_LBN (3)
++#define PMA_PMD_BIST_PMA_LBN (2)
++#define PMA_PMD_BIST_RXD_LBN (1)
++#define PMA_PMD_BIST_AFE_LBN (0)
++
++/* Special Software reset register */
++#define PMA_PMD_EXT_CTRL_REG 49152
++#define PMA_PMD_EXT_SSR_LBN 15
++
++#define BIST_MAX_DELAY (1000)
++#define BIST_POLL_DELAY (10)
++
++static const char *bist_names[] = {
++ [PMA_PMD_BIST_AFE_LBN] = "AFE communication",
++ [PMA_PMD_BIST_RXD_LBN] = "RX data path",
++ [PMA_PMD_BIST_PMA_LBN] = "PMA loopback",
++ [PMA_PMD_BIST_ENX_LBN] = "ENX"
++};
++
++/* Identifier registers: each identifier has 4 part number and 2 revision
++ * registers starting at one of these addresses */
++#define PMA_PMD_AFE_ID_REG 49174
++#define PMA_PMD_DSP_ID_REG 49180
++#define PMA_PMD_FIRMWARE_ID_REG 49186
++
++/* Misc register defines */
++#define PCS_CLOCK_CTRL_REG 0xd801
++#define PLL312_RST_N_LBN 2
++
++#define PCS_SOFT_RST2_REG 0xd806
++#define SERDES_RST_N_LBN 13
++#define XGXS_RST_N_LBN 12
++
++#define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */
++#define CLK312_EN_LBN 3
++
++/* PHYXS registers */
++#define PHYXS_TEST1 (49162)
++#define LOOPBACK_NEAR_LBN (8)
++#define LOOPBACK_NEAR_WIDTH (1)
++
++/* Boot status register */
++#define PCS_BOOT_STATUS_REG (0xd000)
++#define PCS_BOOT_FATAL_ERR_LBN (0)
++#define PCS_BOOT_PROGRESS_LBN (1)
++#define PCS_BOOT_PROGRESS_WIDTH (2)
++#define PCS_BOOT_COMPLETE_LBN (3)
++
++#define PCS_BOOT_MAX_DELAY (100)
++#define PCS_BOOT_POLL_DELAY (10)
++
++#define TENXPRESS_ID_PN_LEN (8)
++#define TENXPRESS_ID_REV_LEN (4)
++#define TENXPRESS_ID_LEN (TENXPRESS_ID_PN_LEN+1+TENXPRESS_ID_REV_LEN)
++
++static const int bist_max = ARRAY_SIZE(bist_names);
++
++/* Time to wait between powering down the LNPGA and turning off the power
++ * rails */
++#define LNPGA_PDOWN_WAIT (HZ / 5)
++
++
++static int crc_error_reset_threshold = 100;
++module_param(crc_error_reset_threshold, int, 0644);
++MODULE_PARM_DESC(crc_error_reset_threshold,
++ "Max number of CRC errors before XAUI reset");
++
++struct tenxpress_phy_data {
++#ifdef CONFIG_SFC_DEBUGFS
++ char phy_snr[4];
++ char phy_afe_id[TENXPRESS_ID_LEN + 1];
++ char phy_dsp_id[TENXPRESS_ID_LEN + 1];
++ char phy_firmware_id[TENXPRESS_ID_LEN + 1];
++ struct efx_nic *efx;
++#endif
++ enum tenxpress_state state;
++ enum efx_loopback_mode loopback_mode;
++ atomic_t bad_crc_count;
++ int phy_powered;
++ int tx_disabled;
++ int bad_lp_tries;
++};
++
++static int tenxpress_state_is(struct efx_nic *efx, int state)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ return (phy_data != NULL) && (state == phy_data->state);
++}
++
++void tenxpress_set_state(struct efx_nic *efx,
++ enum tenxpress_state state)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ if (phy_data != NULL)
++ phy_data->state = state;
++}
++
++void tenxpress_crc_err(struct efx_nic *efx)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ if (phy_data != NULL)
++ atomic_inc(&phy_data->bad_crc_count);
++}
++
++#ifdef CONFIG_SFC_DEBUGFS
++
++/* debugfs entries for this PHY */
++static int tenxpress_ber_read(struct seq_file *file, void *data)
++{
++ struct efx_nic *efx = *(struct efx_nic **)data;
++ int reg, ber;
++
++ reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PCS,
++ MDIO_PCS_10GBT_STATUS2);
++
++ /* Extract the BER */
++ ber = (reg >> MDIO_PCS_10GBT_STATUS2_BER_LBN) &
++ ((1 << MDIO_PCS_10GBT_STATUS2_BER_WIDTH) - 1);
++
++ return seq_printf(file, "%d", ber);
++}
++
++
++static int tenxpress_snr_read(struct seq_file *file, void *data)
++{
++ struct tenxpress_phy_data *phy_data = NULL;
++ struct efx_nic *efx;
++ int lane = *(char *) data;
++ int reg, snr;
++
++ EFX_BUG_ON_PARANOID(lane < 0 || lane >= 4);
++ phy_data = container_of(data, struct tenxpress_phy_data, phy_snr[lane]);
++ efx = phy_data->efx;
++
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, PMA_PMD_SNR_MARGIN_0 + lane);
++
++ /* Convert from SNR margin to SNR to match phychk output */
++ snr = (reg - 0x8000 + 238);
++
++ return seq_printf(file, "%d.%d", snr / 10, snr % 10);
++}
++
++
++static struct efx_debugfs_parameter debug_entries[] = {
++ EFX_PER_LANE_PARAMETER("phy_lane", "_snr",
++ struct tenxpress_phy_data, phy_snr, char,
++ tenxpress_snr_read),
++ EFX_NAMED_PARAMETER(phy_ber, struct tenxpress_phy_data, efx,
++ struct efx_nic *, tenxpress_ber_read),
++ EFX_STRING_PARAMETER(struct tenxpress_phy_data, phy_afe_id),
++ EFX_STRING_PARAMETER(struct tenxpress_phy_data, phy_dsp_id),
++ EFX_STRING_PARAMETER(struct tenxpress_phy_data, phy_firmware_id),
++ {NULL}
++};
++
++static void tenxpress_phy_get_id(struct efx_nic *efx,
++ char *id_buf, int id_addr)
++{
++ int i, reg;
++ char ch;
++
++ for (i = TENXPRESS_ID_PN_LEN / 2 - 1; i >= 0; --i) {
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, id_addr + i);
++ ch = reg & 0xFF;
++ *id_buf++ = ch ? ch : ' ';
++ ch = (reg & 0xFF00) >> 8;
++ *id_buf++ = ch ? ch : ' ';
++ }
++ *id_buf++ = ' ';
++ for (i = TENXPRESS_ID_REV_LEN / 2 - 1; i >= 0; --i) {
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD,
++ id_addr + TENXPRESS_ID_PN_LEN / 2 + i);
++ ch = reg & 0xFF;
++ *id_buf++ = ch ? ch : ' ';
++ ch = (reg & 0xFF00) >> 8;
++ *id_buf++ = ch ? ch : ' ';
++ }
++}
++
++static int tenxpress_debugfs_init(struct efx_nic *efx)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ int lane, rc;
++
++ for (lane = 0; lane < 4; lane++)
++ phy_data->phy_snr[lane] = lane;
++
++ phy_data->efx = efx;
++ rc = efx_extend_debugfs_port(efx, efx->phy_data,
++ debug_entries);
++ if (rc < 0)
++ return rc;
++
++ tenxpress_phy_get_id(efx, phy_data->phy_afe_id,
++ PMA_PMD_AFE_ID_REG);
++ tenxpress_phy_get_id(efx, phy_data->phy_dsp_id,
++ PMA_PMD_DSP_ID_REG);
++ tenxpress_phy_get_id(efx, phy_data->phy_firmware_id,
++ PMA_PMD_FIRMWARE_ID_REG);
++
++ return 0;
++}
++
++#endif /* CONFIG_SFC_DEBUGFS */
++
++/* Check that the C166 has booted successfully */
++static int tenxpress_phy_check(struct efx_nic *efx)
++{
++ int phy_id = efx->mii.phy_id;
++ int count = PCS_BOOT_MAX_DELAY / PCS_BOOT_POLL_DELAY;
++ int boot_stat;
++
++ /* Wait for the boot to complete (or not) */
++ while (count) {
++ boot_stat = mdio_clause45_read(efx, phy_id,
++ MDIO_MMD_PCS,
++ PCS_BOOT_STATUS_REG);
++ if (boot_stat & (1 << PCS_BOOT_COMPLETE_LBN))
++ break;
++ count--;
++ udelay(PCS_BOOT_POLL_DELAY);
++ }
++
++ if (!count) {
++ EFX_ERR(efx, "%s: PHY boot timed out. Last status "
++ "%x\n", __func__,
++ (boot_stat >> PCS_BOOT_PROGRESS_LBN) &
++ ((1 << PCS_BOOT_PROGRESS_WIDTH) - 1));
++ return -ETIMEDOUT;
++ }
++
++ return 0;
++}
++
++static void tenxpress_reset_xaui(struct efx_nic *efx);
++
++/* Initialise the part post power on reset or software special reset */
++static int tenxpress_init(struct efx_nic *efx)
++{
++ int rc, reg;
++
++ /* Turn on the clock */
++ reg = (1 << CLK312_EN_LBN);
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ MDIO_MMD_PCS, PCS_TEST_SELECT_REG, reg);
++
++ rc = tenxpress_phy_check(efx);
++ if (rc < 0)
++ return rc;
++
++ /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG);
++ reg |= (1 << PMA_PMA_LED_ACTIVITY_LBN);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_LED_CTRL_REG, reg);
++
++ reg = PMA_PMD_LED_DEFAULT;
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_LED_OVERR_REG, reg);
++
++ return rc;
++}
++
++static int tenxpress_phy_init(struct efx_nic *efx)
++{
++ struct tenxpress_phy_data *phy_data;
++ int rc = 0;
++
++ phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
++ efx->phy_data = phy_data;
++ phy_data->phy_powered = efx->phy_powered;
++
++ tenxpress_set_state(efx, TENXPRESS_STATUS_NORMAL);
++
++ rc = mdio_clause45_wait_reset_mmds(efx,
++ TENXPRESS_REQUIRED_DEVS);
++ if (rc < 0)
++ goto fail;
++
++ rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
++ if (rc < 0)
++ goto fail;
++
++ rc = tenxpress_init(efx);
++ if (rc < 0)
++ goto fail;
++
++#ifdef CONFIG_SFC_DEBUGFS
++ rc = tenxpress_debugfs_init(efx);
++ if (rc < 0)
++ goto fail;
++#endif
++
++ schedule_timeout_uninterruptible(HZ / 5); /* 200ms */
++
++ /* Let XGXS and SerDes out of reset and resets 10XPress */
++ falcon_reset_xaui(efx);
++
++ return 0;
++
++ fail:
++ kfree(efx->phy_data);
++ efx->phy_data = NULL;
++ return rc;
++}
++
++static int tenxpress_special_reset(struct efx_nic *efx)
++{
++ int rc, reg;
++
++ EFX_TRACE(efx, "%s\n", __func__);
++
++ /* Initiate reset */
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, PMA_PMD_EXT_CTRL_REG);
++ reg |= (1 << PMA_PMD_EXT_SSR_LBN);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_EXT_CTRL_REG, reg);
++
++ msleep(200);
++
++ /* Wait for the blocks to come out of reset */
++ rc = mdio_clause45_wait_reset_mmds(efx,
++ TENXPRESS_REQUIRED_DEVS);
++ if (rc < 0)
++ return rc;
++
++ /* Try and reconfigure the device */
++ rc = tenxpress_init(efx);
++ if (rc < 0)
++ return rc;
++
++ return 0;
++}
++
++static void tenxpress_set_bad_lp(struct efx_nic *efx, int bad_lp)
++{
++ struct tenxpress_phy_data *pd = efx->phy_data;
++ int reg;
++
++ /* Nothing to do if all is well and was previously so. */
++ if (!(bad_lp || pd->bad_lp_tries))
++ return;
++
++ reg = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG);
++
++ if (bad_lp)
++ pd->bad_lp_tries++;
++ else
++ pd->bad_lp_tries = 0;
++
++ if (pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
++ pd->bad_lp_tries = 0; /* Restart count */
++ reg &= ~(PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN);
++ reg |= (PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN);
++ EFX_ERR(efx, "This NIC appears to be plugged into"
++ " a port that is not 10GBASE-T capable.\n"
++ " This PHY is 10GBASE-T ONLY, so no link can"
++ " be established.\n");
++ } else {
++ reg |= (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN);
++ }
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_LED_OVERR_REG, reg);
++}
++
++/* Check link status and return a boolean OK value. If the link is NOT
++ * OK we have a quick rummage round to see if we appear to be plugged
++ * into a non-10GBT port and if so warn the user that they won't get
++ * link any time soon as we are 10GBT only, unless caller specified
++ * not to do this check (it isn't useful in loopback) */
++static int tenxpress_link_ok(struct efx_nic *efx, int check_lp)
++{
++ int ok = mdio_clause45_links_ok(efx, TENXPRESS_REQUIRED_DEVS);
++
++ if (ok) {
++ tenxpress_set_bad_lp(efx, 0);
++ } else if (check_lp) {
++ /* Are we plugged into the wrong sort of link? */
++ int bad_lp = 0;
++ int phy_id = efx->mii.phy_id;
++ int an_stat = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
++ MDIO_AN_STATUS);
++ int xphy_stat = mdio_clause45_read(efx, phy_id,
++ MDIO_MMD_PMAPMD,
++ PMA_PMD_XSTATUS_REG);
++ /* Are we plugged into anything that sends FLPs? If
++ * not we can't distinguish between not being plugged
++ * in and being plugged into a non-AN antique. The FLP
++ * bit has the advantage of not clearing when autoneg
++ * restarts. */
++ if (!(xphy_stat & (1 << PMA_PMD_XSTAT_FLP_LBN))) {
++ tenxpress_set_bad_lp(efx, 0);
++ return ok;
++ }
++
++ /* If it can do 10GBT it must be XNP capable */
++ bad_lp = !(an_stat & (1 << MDIO_AN_STATUS_XNP_LBN));
++ if (!bad_lp && (an_stat & (1 << MDIO_AN_STATUS_PAGE_LBN))) {
++ bad_lp = !(mdio_clause45_read(efx, phy_id,
++ MDIO_MMD_AN, MDIO_AN_10GBT_STATUS) &
++ (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN));
++ }
++ tenxpress_set_bad_lp(efx, bad_lp);
++ }
++ return ok;
++}
++
++static void tenxpress_phyxs_loopback(struct efx_nic *efx)
++{
++ int phy_id = efx->mii.phy_id;
++ int ctrl1, ctrl2;
++
++ ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
++ PHYXS_TEST1);
++ if (efx->loopback_mode == LOOPBACK_PHYXS)
++ ctrl2 |= (1 << LOOPBACK_NEAR_LBN);
++ else
++ ctrl2 &= ~(1 << LOOPBACK_NEAR_LBN);
++ if (ctrl1 != ctrl2)
++ mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS,
++ PHYXS_TEST1, ctrl2);
++}
++
++static void tenxpress_phy_reconfigure(struct efx_nic *efx)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ int loop_change = LOOPBACK_OUT_OF(phy_data, efx,
++ TENXPRESS_LOOPBACKS);
++
++ if (!tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL))
++ return;
++
++ /* When coming out of transmit disable, coming out of low power
++ * mode, or moving out of any PHY internal loopback mode,
++ * perform a special software reset */
++ if (((efx->phy_powered && !efx->tx_disabled) &&
++ (!phy_data->phy_powered || phy_data->tx_disabled)) ||
++ loop_change) {
++ (void) tenxpress_special_reset(efx);
++ falcon_reset_xaui(efx);
++ }
++
++ mdio_clause45_transmit_disable(efx, efx->tx_disabled);
++ mdio_clause45_phy_reconfigure(efx);
++ tenxpress_phyxs_loopback(efx);
++
++ phy_data->tx_disabled = efx->tx_disabled;
++ phy_data->loopback_mode = efx->loopback_mode;
++ phy_data->phy_powered = efx->phy_powered;
++ efx->link_up = tenxpress_link_ok(efx, 0);
++ efx->link_options = GM_LPA_10000FULL;
++}
++
++static void tenxpress_phy_clear_interrupt(struct efx_nic *efx)
++{
++ /* Nothing done here - LASI interrupts aren't reliable so poll */
++}
++
++
++/* Poll PHY for interrupt */
++static int tenxpress_phy_check_hw(struct efx_nic *efx)
++{
++ struct tenxpress_phy_data *phy_data = efx->phy_data;
++ int phy_up = tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL);
++ int link_ok, rc = 0;
++
++ link_ok = phy_up && tenxpress_link_ok(efx, 1);
++
++ if (link_ok != efx->link_up) {
++ efx->link_up = link_ok;
++ efx->mac_op->fake_phy_event(efx);
++ }
++
++ /* Nothing to check if we've already shut down the PHY */
++ if (!phy_up)
++ return 0;
++
++ if (atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
++ EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n");
++ falcon_reset_xaui(efx);
++ atomic_set(&phy_data->bad_crc_count, 0);
++ }
++
++ rc = efx->board_info.monitor(efx);
++ if (rc)
++ efx->link_up = 0;
++
++ return rc;
++}
++
++static void tenxpress_phy_fini(struct efx_nic *efx)
++{
++ int reg;
++
++#ifdef CONFIG_SFC_DEBUGFS
++ efx_trim_debugfs_port(efx, debug_entries);
++#endif
++ /* Power down the LNPGA */
++ reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_XCONTROL_REG, reg);
++
++ /* Waiting here ensures that the board fini, which can turn off the
++ * power to the PHY, won't get run until the LNPGA powerdown has been
++ * given long enough to complete. */
++ schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */
++
++ kfree(efx->phy_data);
++ efx->phy_data = NULL;
++}
++
++
++/* Set the RX and TX LEDs and Link LED flashing. The other LEDs
++ * (which probably aren't wired anyway) are left in AUTO mode */
++void tenxpress_phy_blink(struct efx_nic *efx, int blink)
++{
++ int reg;
++
++ if (blink)
++ reg = (PMA_PMD_LED_FLASH << PMA_PMD_LED_TX_LBN) |
++ (PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN) |
++ (PMA_PMD_LED_FLASH << PMA_PMD_LED_LINK_LBN);
++ else
++ reg = PMA_PMD_LED_DEFAULT;
++
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ PMA_PMD_LED_OVERR_REG, reg);
++}
++
++static void tenxpress_reset_xaui(struct efx_nic *efx)
++{
++ int phy = efx->mii.phy_id;
++ int clk_ctrl, test_select, soft_rst2;
++
++ /* Real work is done on clock_ctrl other resets are thought to be
++ * optional but make the reset more reliable
++ */
++
++ /* Read */
++ clk_ctrl = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
++ PCS_CLOCK_CTRL_REG);
++ test_select = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
++ PCS_TEST_SELECT_REG);
++ soft_rst2 = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
++ PCS_SOFT_RST2_REG);
++
++ /* Modify => put in reset */
++ test_select &= ~(1 << CLK312_EN_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_TEST_SELECT_REG, test_select);
++
++ soft_rst2 &= ~((1 << XGXS_RST_N_LBN) | (1 << SERDES_RST_N_LBN));
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_SOFT_RST2_REG, soft_rst2);
++
++ clk_ctrl &= ~(1 << PLL312_RST_N_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_CLOCK_CTRL_REG, clk_ctrl);
++ udelay(10);
++
++ /* Modify => remove reset */
++ clk_ctrl |= (1 << PLL312_RST_N_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_CLOCK_CTRL_REG, clk_ctrl);
++ udelay(10);
++
++ soft_rst2 |= ((1 << XGXS_RST_N_LBN) | (1 << SERDES_RST_N_LBN));
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_SOFT_RST2_REG, soft_rst2);
++ udelay(10);
++
++ test_select |= (1 << CLK312_EN_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ PCS_TEST_SELECT_REG, test_select);
++ udelay(10);
++}
++
++
++struct efx_phy_operations falcon_tenxpress_phy_ops = {
++ .init = tenxpress_phy_init,
++ .reconfigure = tenxpress_phy_reconfigure,
++ .check_hw = tenxpress_phy_check_hw,
++ .fini = tenxpress_phy_fini,
++ .clear_interrupt = tenxpress_phy_clear_interrupt,
++ .reset_xaui = tenxpress_reset_xaui,
++ .mmds = TENXPRESS_REQUIRED_DEVS,
++ .loopbacks = TENXPRESS_LOOPBACKS,
++ .startup_loopback = LOOPBACK_PCS,
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/tx.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/tx.c
+--- linux-2.6.18.8/drivers/net/sfc/tx.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/tx.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,522 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2005-2006: Fen Systems Ltd.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/pci.h>
++#include <linux/tcp.h>
++#include <linux/ip.h>
++#include <linux/in.h>
++#include <linux/if_ether.h>
++#include <linux/version.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++#include <linux/highmem.h>
++#endif
++#include "net_driver.h"
++#include "tx.h"
++#include "efx.h"
++#include "falcon.h"
++#include "workarounds.h"
++
++
++/*
++ * TX descriptor ring full threshold
++ *
++ * The tx_queue descriptor ring fill-level must fall below this value
++ * before we restart the netif queue
++ */
++#define EFX_NETDEV_TX_THRESHOLD(_tx_queue) \
++ (_tx_queue->efx->type->txd_ring_mask / 2u)
++
++
++
++/* We want to be able to nest calls to netif_stop_queue(), since each
++ * channel can have an individual stop on the queue.
++ */
++void efx_stop_queue(struct efx_nic *efx)
++{
++ spin_lock_bh(&efx->netif_stop_lock);
++ EFX_TRACE(efx, "stop TX queue\n");
++
++ atomic_inc(&efx->netif_stop_count);
++ if (likely(efx->net_dev_registered))
++ netif_stop_queue(efx->net_dev);
++
++ spin_unlock_bh(&efx->netif_stop_lock);
++}
++
++/* Wake netif's TX queue
++ * We want to be able to nest calls to netif_stop_queue(), since each
++ * channel can have an individual stop on the queue.
++ */
++inline void efx_wake_queue(struct efx_nic *efx)
++{
++ local_bh_disable();
++ if (atomic_dec_and_lock(&efx->netif_stop_count,
++ &efx->netif_stop_lock)) {
++ EFX_TRACE(efx, "waking TX queue\n");
++ if (likely(efx->net_dev_registered))
++ netif_wake_queue(efx->net_dev);
++ spin_unlock(&efx->netif_stop_lock);
++ }
++ local_bh_enable();
++}
++
++/*
++ * Add a socket buffer to a TX queue
++ *
++ * This maps all fragments of a socket buffer for DMA and adds them to
++ * the TX queue. The queue's insert pointer will be incremented by
++ * the number of fragments in the socket buffer.
++ *
++ * If any DMA mapping fails, any mapped fragments will be unmapped,
++ * the queue's insert pointer will be restored to its original value.
++ *
++ * Returns NETDEV_TX_OK or NETDEV_TX_BUSY
++ * You must hold netif_tx_lock() to call this function.
++ */
++static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
++ const struct sk_buff *skb)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ struct pci_dev *pci_dev = efx->pci_dev;
++ struct efx_tx_buffer *buffer;
++ skb_frag_t *fragment;
++ struct page *page;
++ int page_offset;
++ unsigned int len, unmap_len = 0, fill_level, insert_ptr, misalign;
++ dma_addr_t dma_addr, unmap_addr = 0;
++ unsigned int dma_len;
++ unsigned unmap_single;
++ int q_space, i = 0;
++ int rc = NETDEV_TX_OK;
++
++ EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count);
++
++ /* Get size of the initial fragment */
++ len = skb_headlen(skb);
++
++ fill_level = tx_queue->insert_count - tx_queue->old_read_count;
++ q_space = efx->type->txd_ring_mask - 1 - fill_level;
++
++ /* Map for DMA. Use pci_map_single rather than pci_map_page
++ * since this is more efficient on machines with sparse
++ * memory.
++ */
++ unmap_single = 1;
++ dma_addr = pci_map_single(pci_dev, skb->data, len, PCI_DMA_TODEVICE);
++
++ /* Process all fragments */
++ while (1) {
++ if (unlikely(pci_dma_mapping_error(dma_addr)))
++ goto pci_err;
++
++ /* Store fields for marking in the per-fragment final
++ * descriptor */
++ unmap_len = len;
++ unmap_addr = dma_addr;
++
++ /* Add to TX queue, splitting across DMA boundaries */
++ do {
++ if (unlikely(q_space-- <= 0)) {
++ /* It might be that completions have
++ * happened since the xmit path last
++ * checked. Update the xmit path's
++ * copy of read_count.
++ */
++ ++tx_queue->stopped;
++ /* This memory barrier protects the
++ * change of stopped from the access
++ * of read_count. */
++ smp_mb();
++ tx_queue->old_read_count =
++ *(volatile unsigned *)
++ &tx_queue->read_count;
++ fill_level = (tx_queue->insert_count
++ - tx_queue->old_read_count);
++ q_space = (efx->type->txd_ring_mask - 1 -
++ fill_level);
++ if (unlikely(q_space-- <= 0))
++ goto stop;
++ smp_mb();
++ --tx_queue->stopped;
++ }
++
++ insert_ptr = (tx_queue->insert_count &
++ efx->type->txd_ring_mask);
++ buffer = &tx_queue->buffer[insert_ptr];
++ EFX_BUG_ON_PARANOID(buffer->skb);
++ EFX_BUG_ON_PARANOID(buffer->len);
++ EFX_BUG_ON_PARANOID(buffer->continuation != 1);
++ EFX_BUG_ON_PARANOID(buffer->unmap_len);
++
++ dma_len = (((~dma_addr) & efx->type->tx_dma_mask) + 1);
++ if (likely(dma_len > len))
++ dma_len = len;
++
++ misalign = (unsigned)dma_addr & efx->type->bug5391_mask;
++ if (misalign && dma_len + misalign > 512)
++ dma_len = 512 - misalign;
++
++ /* Fill out per descriptor fields */
++ buffer->len = dma_len;
++ buffer->dma_addr = dma_addr;
++ len -= dma_len;
++ dma_addr += dma_len;
++ ++tx_queue->insert_count;
++ } while (len);
++
++ /* Transfer ownership of the unmapping to the final buffer */
++ buffer->unmap_addr = unmap_addr;
++ buffer->unmap_single = unmap_single;
++ buffer->unmap_len = unmap_len;
++ unmap_len = 0;
++
++ /* Get address and size of next fragment */
++ if (i >= skb_shinfo(skb)->nr_frags)
++ break;
++ fragment = &skb_shinfo(skb)->frags[i];
++ len = fragment->size;
++ page = fragment->page;
++ page_offset = fragment->page_offset;
++ i++;
++ /* Map for DMA */
++ unmap_single = 0;
++ dma_addr = pci_map_page(pci_dev, page, page_offset, len,
++ PCI_DMA_TODEVICE);
++ }
++
++ /* Transfer ownership of the skb to the final buffer */
++ buffer->skb = skb;
++ buffer->continuation = 0;
++
++ /* Pass off to hardware */
++ falcon_push_buffers(tx_queue);
++
++ return NETDEV_TX_OK;
++
++ pci_err:
++ EFX_ERR_RL(efx, " TX queue %d could not map skb with %d bytes %d "
++ "fragments for DMA\n", tx_queue->queue, skb->len,
++ skb_shinfo(skb)->nr_frags + 1);
++
++ /* Mark the packet as transmitted, and free the SKB ourselves */
++ dev_kfree_skb_any((struct sk_buff *)skb);
++ goto unwind;
++
++ stop:
++ rc = NETDEV_TX_BUSY;
++
++ /* Stop the queue if it wasn't stopped before. */
++ if (tx_queue->stopped == 1)
++ efx_stop_queue(efx);
++
++ unwind:
++ /* Work backwards until we hit the original insert pointer value */
++ while (tx_queue->insert_count != tx_queue->write_count) {
++ --tx_queue->insert_count;
++ insert_ptr = tx_queue->insert_count & efx->type->txd_ring_mask;
++ buffer = &tx_queue->buffer[insert_ptr];
++ if (buffer->unmap_len) {
++ if (buffer->unmap_single)
++ pci_unmap_single(pci_dev, buffer->unmap_addr,
++ buffer->unmap_len,
++ PCI_DMA_TODEVICE);
++ else
++ pci_unmap_page(pci_dev, buffer->unmap_addr,
++ buffer->unmap_len,
++ PCI_DMA_TODEVICE);
++ }
++ buffer->unmap_len = 0;
++ buffer->len = 0;
++ }
++
++ /* Free the fragment we were mid-way through pushing */
++ if (unmap_len)
++ pci_unmap_page(pci_dev, unmap_addr, unmap_len,
++ PCI_DMA_TODEVICE);
++
++ return rc;
++}
++
++/* Remove packets from the TX queue
++ *
++ * This removes packets from the TX queue, up to and including the
++ * specified index.
++ */
++static inline void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
++ unsigned int index)
++{
++ struct pci_dev *pci_dev = tx_queue->efx->pci_dev;
++ struct efx_tx_buffer *buffer;
++ unsigned int stop_index, read_ptr;
++
++ /* Calculate the stopping point. Doing the check this way
++ * avoids wrongly completing every buffer in the ring if we
++ * get called twice with the same index. (Hardware should
++ * never do this, since it can't complete that many buffers in
++ * one go.)
++ */
++ stop_index = (index + 1) & tx_queue->efx->type->txd_ring_mask;
++ read_ptr = tx_queue->read_count & tx_queue->efx->type->txd_ring_mask;
++
++ while (read_ptr != stop_index) {
++ buffer = &tx_queue->buffer[read_ptr];
++ if (unlikely(buffer->len == 0)) {
++ EFX_ERR(tx_queue->efx, "TX queue %d spurious TX "
++ "completion id %x\n", tx_queue->queue,
++ read_ptr);
++ atomic_inc(&tx_queue->efx->errors.spurious_tx);
++ /* Don't reset */
++ } else {
++ if (buffer->unmap_len) {
++ if (buffer->unmap_single)
++ pci_unmap_single(pci_dev,
++ buffer->unmap_addr,
++ buffer->unmap_len,
++ PCI_DMA_TODEVICE);
++ else
++ pci_unmap_page(pci_dev,
++ buffer->unmap_addr,
++ buffer->unmap_len,
++ PCI_DMA_TODEVICE);
++ buffer->unmap_single = 0;
++ buffer->unmap_len = 0;
++ }
++ if (buffer->skb) {
++ dev_kfree_skb_any((struct sk_buff *)
++ buffer->skb);
++ buffer->skb = NULL;
++ EFX_TRACE(tx_queue->efx, "TX queue %d "
++ "transmission id %x complete\n",
++ tx_queue->queue, read_ptr);
++ }
++ buffer->continuation = 1;
++ buffer->len = 0;
++ }
++ ++tx_queue->read_count;
++ read_ptr = (tx_queue->read_count &
++ tx_queue->efx->type->txd_ring_mask);
++ }
++}
++
++/* Initiate a packet transmission on the specified TX queue.
++ * Note that returning anything other than NETDEV_TX_OK will cause the
++ * OS to free the skb.
++ *
++ * This function is split out from efx_hard_start_xmit to allow the
++ * loopback test to direct packets via specific TX queues. It is
++ * therefore a non-static inline, so as not to penalise performance
++ * for non-loopback transmissions.
++ *
++ * Context: netif_tx_lock held
++ */
++inline int efx_xmit(struct efx_nic *efx,
++ struct efx_tx_queue *tx_queue, struct sk_buff *skb)
++{
++ int rc;
++
++ /* Map fragments for DMA and add to TX queue */
++ rc = efx_enqueue_skb(tx_queue, skb);
++ if (unlikely(rc != NETDEV_TX_OK))
++ goto out;
++
++ /* Update last TX timer */
++ efx->net_dev->trans_start = jiffies;
++
++ out:
++ return rc;
++}
++
++/* Initiate a packet transmission. We use one channel per CPU
++ * (sharing when we have more CPUs than channels). On Falcon, the TX
++ * completion events will be directed back to the CPU that transmitted
++ * the packet, which should be cache-efficient.
++ *
++ * Context: non-blocking.
++ * Note that returning anything other than NETDEV_TX_OK will cause the
++ * OS to free the skb.
++ */
++int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
++{
++ struct efx_nic *efx = net_dev->priv;
++ struct efx_tx_queue *tx_queue;
++ enum efx_veto veto;
++ int rc = NETDEV_TX_OK;
++
++ /* We have one TX queue. */
++ tx_queue = &efx->tx_queue[0];
++
++ /* See if driverlink wants to veto the packet. */
++ veto = EFX_DL_CALLBACK(efx, tx_packet, skb);
++ if (unlikely(veto)) {
++ EFX_LOG(efx, "TX queue %d packet vetoed by "
++ "driverlink %s driver\n", tx_queue->queue,
++ efx->dl_cb_dev.tx_packet->driver->name);
++ /* Free the skb; nothing else will do it */
++ dev_kfree_skb_any((struct sk_buff *)skb);
++ goto out;
++ }
++
++ rc = efx_xmit(efx, tx_queue, skb);
++out:
++ return rc;
++}
++
++#if defined(EFX_USE_FASTCALL)
++void fastcall efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
++#else
++void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
++#endif
++{
++ unsigned long flags __attribute__ ((unused));
++ unsigned fill_level;
++ struct efx_nic *efx = tx_queue->efx;
++
++ EFX_BUG_ON_PARANOID(index > efx->type->txd_ring_mask);
++
++ /* Remove buffers from TX queue */
++ efx_dequeue_buffers(tx_queue, index);
++
++ /* See if we need to restart the netif queue. This barrier
++ * separates the update of read_count from the test of
++ * stopped. */
++ smp_mb();
++ if (unlikely(tx_queue->stopped)) {
++ fill_level = tx_queue->insert_count - tx_queue->read_count;
++ if (fill_level < EFX_NETDEV_TX_THRESHOLD(tx_queue)) {
++ /* If the port is stopped and the net_dev isn't
++ * registered, then the caller must be performing
++ * flow control manually */
++ if (unlikely(!efx->net_dev_registered))
++ return;
++
++ /* Do this under netif_tx_lock(), to avoid racing
++ * with efx_xmit(). */
++ netif_tx_lock(efx->net_dev);
++ if (tx_queue->stopped) {
++ tx_queue->stopped = 0;
++ efx_wake_queue(efx);
++ }
++ netif_tx_unlock(efx->net_dev);
++ }
++ }
++}
++
++int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ struct efx_nic *efx = tx_queue->efx;
++ unsigned int txq_size;
++ int i, rc;
++
++ EFX_LOG(efx, "creating TX queue %d\n", tx_queue->queue);
++
++ /* Allocate software ring */
++ txq_size = (efx->type->txd_ring_mask + 1) * sizeof(*tx_queue->buffer);
++ tx_queue->buffer = kzalloc(txq_size, GFP_KERNEL);
++ if (!tx_queue->buffer) {
++ rc = -ENOMEM;
++ goto fail1;
++ }
++ for (i = 0; i <= efx->type->txd_ring_mask; ++i)
++ tx_queue->buffer[i].continuation = 1;
++
++ /* Allocate hardware ring */
++ rc = falcon_probe_tx(tx_queue);
++ if (rc)
++ goto fail2;
++
++ return 0;
++
++ fail2:
++ kfree(tx_queue->buffer);
++ tx_queue->buffer = NULL;
++ fail1:
++ /* Mark queue as unused */
++ tx_queue->used = 0;
++
++ return rc;
++}
++
++int efx_init_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ EFX_LOG(tx_queue->efx, "initialising TX queue %d\n", tx_queue->queue);
++
++ ASSERT_RTNL();
++
++ /* Initialise fields */
++ tx_queue->insert_count = 0;
++ tx_queue->write_count = 0;
++ tx_queue->read_count = 0;
++ tx_queue->old_read_count = 0;
++ BUG_ON(tx_queue->stopped);
++
++ /* Set up TX descriptor ring */
++ return falcon_init_tx(tx_queue);
++}
++
++void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
++{
++ unsigned int last_index, mask;
++ if (tx_queue->buffer) {
++ /* Free any buffers left in the ring */
++ mask = tx_queue->efx->type->txd_ring_mask;
++ last_index = (tx_queue->insert_count - 1) & mask;
++ EFX_LOG(tx_queue->efx, "Will dequeue up to 0x%x from 0x%x\n",
++ last_index, tx_queue->read_count & mask);
++ efx_dequeue_buffers(tx_queue, last_index);
++ }
++}
++
++void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ EFX_LOG(tx_queue->efx, "shutting down TX queue %d\n", tx_queue->queue);
++
++ ASSERT_RTNL();
++
++ /* Flush TX queue, remove descriptor ring */
++ falcon_fini_tx(tx_queue);
++
++ /* Release TX buffers */
++ efx_release_tx_buffers(tx_queue);
++
++ /* Release queue's stop on port, if any */
++ if (tx_queue->stopped) {
++ tx_queue->stopped = 0;
++ efx_wake_queue(tx_queue->efx);
++ }
++}
++
++void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
++{
++ EFX_LOG(tx_queue->efx, "destroying TX queue %d\n", tx_queue->queue);
++ falcon_remove_tx(tx_queue);
++
++ kfree(tx_queue->buffer);
++ tx_queue->buffer = NULL;
++ tx_queue->used = 0;
++}
++
++
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/txc43128_phy.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/txc43128_phy.c
+--- linux-2.6.18.8/drivers/net/sfc/txc43128_phy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/txc43128_phy.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,725 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++/*
++ * Driver for Transwitch/Mysticom CX4 retimer
++ * see www.transwitch.com, part is TXC-43128
++ */
++
++#include <linux/delay.h>
++#include <linux/seq_file.h>
++#include "efx.h"
++#include "debugfs.h"
++#include "gmii.h"
++#include "mdio_10g.h"
++#include "xenpack.h"
++#include "phy.h"
++#include "lm87_support.h"
++#include "falcon.h"
++#include "workarounds.h"
++
++/* We expect these MMDs to be in the package */
++#define TXC_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PCS | \
++ MDIO_MMDREG_DEVS0_PMAPMD | \
++ MDIO_MMDREG_DEVS0_PHYXS)
++
++#define TXC_LOOPBACKS ((1 << LOOPBACK_PCS) | \
++ (1 << LOOPBACK_PMAPMD) | \
++ (1 << LOOPBACK_NETWORK))
++
++/**************************************************************************
++ *
++ * Compile-time config
++ *
++ **************************************************************************
++ */
++#define TXCNAME "TXC43128"
++/* Total length of time we'll wait for the PHY to come out of reset */
++#define TXC_MAX_RESET_TIME 500
++/* Interval between checks */
++#define TXC_RESET_WAIT 10
++/* How long to run BIST: At 10Gbps 50 microseconds should be plenty to get
++ * some stats */
++#define TXC_BIST_DURATION (50)
++
++#define BER_INTERVAL (10 * efx_monitor_interval)
++
++/**************************************************************************
++ *
++ * Register definitions
++ *
++ **************************************************************************
++ */
++#define XAUI_NUM_LANES (4)
++
++/*** Global register bank */
++/* Silicon ID register */
++#define TXC_GLRGS_SLID (0xc000)
++#define TXC_GLRGS_SLID_MASK (0x1f)
++
++/* Command register */
++#define TXC_GLRGS_GLCMD (0xc004)
++/* Useful bits in command register */
++/* Lane power-down */
++#define TXC_GLCMD_L01PD_LBN (5)
++#define TXC_GLCMD_L23PD_LBN (6)
++/* Limited SW reset: preserves configuration but
++ * initiates a logic reset. Self-clearing */
++#define TXC_GLCMD_LMTSWRST_LBN (14)
++
++/* Signal Quality Control */
++#define TXC_GLRGS_GSGQLCTL (0xc01a)
++/* Enable bit */
++#define TXC_GSGQLCT_SGQLEN_LBN (15)
++/* Lane selection */
++#define TXC_GSGQLCT_LNSL_LBN (13)
++#define TXC_GSGQLCT_LNSL_WIDTH (2)
++
++/* Signal Quality Input */
++#define TXC_GLRGS_GSGQLIN (0xc01b)
++/* Signal Quality Grade */
++#define TXC_GLRGS_GSGQLGRD (0xc01c)
++/* Drift sign */
++#define TXC_GSGQLGRD_DRFTSGN_LBN (15)
++/* Grade valid flag */
++#define TXC_GSGQLGRD_GRDVAL_LBN (14)
++/* Remaining bits are the actual grade */
++#define TXC_GSGQLGRD_GRADE_LBN (0)
++#define TXC_GSGQLGRD_GRADE_WIDTH (14)
++
++/* Signal Quality Drift: 16-bit drift value */
++#define TXC_GLRGS_GSGQLDRFT (0xc01d)
++
++/**** Analog register bank */
++#define TXC_ALRGS_ATXCTL (0xc040)
++/* Lane power-down */
++#define TXC_ATXCTL_TXPD3_LBN (15)
++#define TXC_ATXCTL_TXPD2_LBN (14)
++#define TXC_ATXCTL_TXPD1_LBN (13)
++#define TXC_ATXCTL_TXPD0_LBN (12)
++
++/* Amplitude on lanes 0, 1 */
++#define TXC_ALRGS_ATXAMP0 (0xc041)
++/* Amplitude on lanes 2, 3 */
++#define TXC_ALRGS_ATXAMP1 (0xc042)
++/* Bit position of value for lane 0 (or 2) */
++#define TXC_ATXAMP_LANE02_LBN (3)
++/* Bit position of value for lane 1 (or 3) */
++#define TXC_ATXAMP_LANE13_LBN (11)
++
++#define TXC_ATXAMP_1280_mV (0)
++#define TXC_ATXAMP_1200_mV (8)
++#define TXC_ATXAMP_1120_mV (12)
++#define TXC_ATXAMP_1060_mV (14)
++#define TXC_ATXAMP_0820_mV (25)
++#define TXC_ATXAMP_0720_mV (26)
++#define TXC_ATXAMP_0580_mV (27)
++#define TXC_ATXAMP_0440_mV (28)
++
++#define TXC_ATXAMP_0820_BOTH \
++ ((TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) \
++ | (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN))
++
++#define TXC_ATXAMP_DEFAULT (0x6060) /* From databook */
++
++/* Preemphasis on lanes 0, 1 */
++#define TXC_ALRGS_ATXPRE0 (0xc043)
++/* Preemphasis on lanes 2, 3 */
++#define TXC_ALRGS_ATXPRE1 (0xc044)
++
++#define TXC_ATXPRE_NONE (0)
++#define TXC_ATXPRE_DEFAULT (0x1010) /* From databook */
++
++#define TXC_ALRGS_ARXCTL (0xc045)
++/* Lane power-down */
++#define TXC_ARXCTL_RXPD3_LBN (15)
++#define TXC_ARXCTL_RXPD2_LBN (14)
++#define TXC_ARXCTL_RXPD1_LBN (13)
++#define TXC_ARXCTL_RXPD0_LBN (12)
++
++/*** receiver control registers: Bit Error Rate measurement */
++/* Per lane BER timers */
++#define TXC_RXCTL_BERTMR0 (0xc0d4)
++#define TXC_RXCTL_BERTMR1 (0xc154)
++#define TXC_RXCTL_BERTMR2 (0xc1d4)
++#define TXC_RXCTL_BERTMR3 (0xc254)
++/* Per lane BER counters */
++#define TXC_RXCTL_BERCNT0 (0xc0d5)
++#define TXC_RXCTL_BERCNT1 (0xc155)
++#define TXC_RXCTL_BERCNT2 (0xc1d5)
++#define TXC_RXCTL_BERCNT3 (0xc255)
++
++#define BER_REG_SPACING (TXC_RXCTL_BERTMR1 - TXC_RXCTL_BERTMR0)
++
++/*** Main user-defined register set */
++/* Main control */
++#define TXC_MRGS_CTL (0xc340)
++/* Bits in main control */
++#define TXC_MCTL_RESET_LBN (15) /* Self clear */
++#define TXC_MCTL_TXLED_LBN (14) /* 1 to show align status */
++#define TXC_MCTL_RXLED_LBN (13) /* 1 to show align status */
++
++/* GPIO output */
++#define TXC_GPIO_OUTPUT (0xc346)
++#define TXC_GPIO_DIR (0xc348)
++
++/*** Vendor-specific BIST registers */
++#define TXC_BIST_CTL (0xc280)
++#define TXC_BIST_TXFRMCNT (0xc281)
++#define TXC_BIST_RX0FRMCNT (0xc282)
++#define TXC_BIST_RX1FRMCNT (0xc283)
++#define TXC_BIST_RX2FRMCNT (0xc284)
++#define TXC_BIST_RX3FRMCNT (0xc285)
++#define TXC_BIST_RX0ERRCNT (0xc286)
++#define TXC_BIST_RX1ERRCNT (0xc287)
++#define TXC_BIST_RX2ERRCNT (0xc288)
++#define TXC_BIST_RX3ERRCNT (0xc289)
++
++/*** BIST control bits */
++/* BIST type (controls bit patter in test) */
++#define TXC_BIST_CTRL_TYPE_LBN (10)
++#define TXC_BIST_CTRL_TYPE_TSD (0) /* TranSwitch Deterministic */
++#define TXC_BIST_CTRL_TYPE_CRP (1) /* CRPAT standard */
++#define TXC_BIST_CTRL_TYPE_CJP (2) /* CJPAT standard */
++#define TXC_BIST_CTRL_TYPE_TSR (3) /* TranSwitch pseudo-random */
++/* Set this to 1 for 10 bit and 0 for 8 bit */
++#define TXC_BIST_CTRL_B10EN_LBN (12)
++/* Enable BIST (write 0 to disable) */
++#define TXC_BIST_CTRL_ENAB_LBN (13)
++/*Stop BIST (self-clears when stop complete) */
++#define TXC_BIST_CTRL_STOP_LBN (14)
++/* Start BIST (cleared by writing 1 to STOP) */
++#define TXC_BIST_CTRL_STRT_LBN (15)
++
++/* Mt. Diablo test configuration */
++#define TXC_MTDIABLO_CTRL (0xc34f)
++#define TXC_MTDIABLO_CTRL_PMA_LOOP_LBN (10)
++
++struct txc43128_data {
++#ifdef CONFIG_SFC_DEBUGFS
++ /* BER stats update from check_hw. Note that this is in errors/second,
++ * converting it to errors/bit is left as an exercise for user-space.
++ */
++ unsigned phy_ber_pcs[4];
++ unsigned phy_ber_phyxs[4];
++#endif
++ unsigned bug10934_timer;
++ int phy_powered;
++ int tx_disabled;
++ enum efx_loopback_mode loopback_mode;
++};
++
++/* Perform the bug 10934 workaround every 5s */
++#define BUG10934_RESET_INTERVAL (5 * HZ)
++
++
++/* Perform a reset that doesn't clear configuration changes */
++static void txc_reset_logic(struct efx_nic *efx);
++
++/* Set the output value of a gpio */
++void txc_set_gpio_val(struct efx_nic *efx, int pin, int on)
++{
++ int outputs;
++
++ outputs = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT);
++
++ outputs = (outputs & ~(1 << pin)) | (on << pin);
++
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT,
++ outputs);
++}
++
++/* Set up the GPIO direction register */
++void txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir)
++{
++ int dirs;
++
++ if (efx->board_info.minor < 3 &&
++ efx->board_info.major == 0)
++ return;
++
++ dirs = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS, TXC_GPIO_DIR);
++ dirs = (dir & ~(1 << pin)) | (dir << pin);
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS, TXC_GPIO_DIR, dirs);
++
++}
++
++/* Reset the PMA/PMD MMD. The documentation is explicit that this does a
++ * global reset (it's less clear what reset of other MMDs does).*/
++static int txc_reset_phy(struct efx_nic *efx)
++{
++ int rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PMAPMD,
++ TXC_MAX_RESET_TIME / TXC_RESET_WAIT,
++ TXC_RESET_WAIT);
++ if (rc < 0)
++ goto fail;
++
++ /* Check that all the MMDs we expect are present and responding. We
++ * expect faults on some if the link is down, but not on the PHY XS */
++ rc = mdio_clause45_check_mmds(efx, TXC_REQUIRED_DEVS, 0);
++ if (rc < 0)
++ goto fail;
++
++ return 0;
++
++ fail:
++ EFX_ERR(efx, TXCNAME ": reset timed out!\n");
++ return rc;
++}
++
++/* Run a single BIST on one MMD*/
++static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
++{
++ int phy = efx->mii.phy_id;
++ int ctrl, bctl;
++ int lane;
++ int rc = 0;
++
++ EFX_INFO(efx, "" TXCNAME ": running BIST on %s MMD\n",
++ mdio_clause45_mmd_name(mmd));
++
++ /* Set PMA to test into loopback using Mt Diablo reg as per app note */
++ ctrl = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
++ TXC_MTDIABLO_CTRL);
++ ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ TXC_MTDIABLO_CTRL, ctrl);
++
++
++ /* The BIST app. note lists these as 3 distinct steps. */
++ /* Set the BIST type */
++ bctl = (test << TXC_BIST_CTRL_TYPE_LBN);
++ mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, bctl);
++
++ /* Set the BSTEN bit in the BIST Control register to enable */
++ bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN);
++ mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, bctl);
++
++ /* Set the BSTRT bit in the BIST Control register */
++ mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, bctl |
++ (1 << TXC_BIST_CTRL_STRT_LBN));
++
++ /* Wait. */
++ udelay(TXC_BIST_DURATION);
++
++ /* Set the BSTOP bit in the BIST Control register */
++ bctl |= (1 << TXC_BIST_CTRL_STOP_LBN);
++ mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, bctl);
++
++ /* The STOP bit should go off when things have stopped */
++ while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN))
++ bctl = mdio_clause45_read(efx, phy, mmd, TXC_BIST_CTL);
++
++ /* Check all the error counts are 0 and all the frame counts are
++ non-zero */
++ for (lane = 0; lane < 4; lane++) {
++ int count = mdio_clause45_read(efx, phy, mmd,
++ TXC_BIST_RX0ERRCNT + lane);
++ if (count != 0) {
++ EFX_ERR(efx, ""TXCNAME": BIST error. "
++ "Lane %d had %d errs\n", lane, count);
++ rc = -EIO;
++ }
++ count = mdio_clause45_read(efx, phy, mmd,
++ TXC_BIST_RX0FRMCNT + lane);
++ if (count == 0) {
++ EFX_ERR(efx, ""TXCNAME": BIST error. "
++ "Lane %d got 0 frames\n", lane);
++ rc = -EIO;
++ }
++ }
++
++ if (rc == 0)
++ EFX_INFO(efx, ""TXCNAME": BIST pass\n");
++
++ /* Disable BIST */
++ mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, 0);
++
++ /* Turn off loopback */
++ ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
++ mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
++ TXC_MTDIABLO_CTRL, ctrl);
++
++ return rc;
++}
++
++/* Run all the desired BIST tests for the PHY */
++static int txc_bist(struct efx_nic *efx)
++{
++ int rc;
++ /*!\todo: experiment with running more of the BIST patterns to
++ * see if it actually shows up more problems. */
++ rc = txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD);
++ return rc;
++}
++
++#ifdef CONFIG_SFC_DEBUGFS
++
++/* debugfs entries for this PHY */
++static struct efx_debugfs_parameter debug_entries[] = {
++ EFX_PER_LANE_PARAMETER("phy_ber_lane", "_pcs",
++ struct txc43128_data, phy_ber_pcs,
++ unsigned, efx_debugfs_read_uint),
++ EFX_PER_LANE_PARAMETER("phy_ber_lane", "_phyxs",
++ struct txc43128_data, phy_ber_phyxs,
++ unsigned, efx_debugfs_read_uint),
++ EFX_INT_PARAMETER(struct txc43128_data, phy_powered),
++ {NULL}
++};
++
++#endif /* CONFIG_SFC_DEBUGFS */
++
++/* Push the non-configurable defaults into the PHY. This must be
++ * done after every full reset */
++static void txc_apply_defaults(struct efx_nic *efx)
++{
++ int mctrl;
++
++ /* Turn amplitude down and preemphasis off on the host side
++ * (PHY<->MAC) as this is believed less likely to upset Falcon
++ * and no adverse effects have been noted. It probably also
++ * saves a picowatt or two */
++
++ /* Turn off preemphasis */
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PHYXS,
++ TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PHYXS,
++ TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE);
++
++ /* Turn down the amplitude */
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PHYXS,
++ TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PHYXS,
++ TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH);
++
++ /* Set the line side amplitude and preemphasis to the databook
++ * defaults as an erratum causes them to be 0 on at least some
++ * PHY rev.s */
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT);
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT);
++
++ /* Set up the LEDs */
++ mctrl = mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS, TXC_MRGS_CTL);
++
++ /* Set the Green and Red LEDs to their default modes */
++ mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN));
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl);
++
++ /* Databook recommends doing this after configuration changes */
++ txc_reset_logic(efx);
++
++ efx->board_info.init_leds(efx);
++}
++
++/* Initialisation entry point for this PHY driver */
++static int txc43128_phy_init(struct efx_nic *efx)
++{
++ u32 devid;
++ int rc = 0;
++ struct txc43128_data *phy_data;
++
++ devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS);
++
++ phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
++ efx->phy_data = phy_data;
++
++ /* This is the default after reset */
++ phy_data->phy_powered = efx->phy_powered;
++ phy_data->tx_disabled = efx->tx_disabled;
++
++#ifdef CONFIG_SFC_DEBUGFS
++ rc = efx_extend_debugfs_port(efx, phy_data, debug_entries);
++ if (rc < 0)
++ goto fail1;
++#endif
++ EFX_INFO(efx, ""TXCNAME ": PHY ID reg %x (OUI %x model %x "
++ "revision %x)\n", devid, MDIO_ID_OUI(devid),
++ MDIO_ID_MODEL(devid), MDIO_ID_REV(devid));
++
++ EFX_INFO(efx, ""TXCNAME ": Silicon ID %x\n",
++ mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PHYXS, TXC_GLRGS_SLID) &
++ TXC_GLRGS_SLID_MASK);
++
++ rc = txc_reset_phy(efx);
++ if (rc < 0)
++ goto fail2;
++
++ rc = txc_bist(efx);
++ if (rc < 0)
++ goto fail2;
++
++ txc_apply_defaults(efx);
++
++ return 0;
++
++ fail2:
++#ifdef CONFIG_SFC_DEBUGFS
++ efx_trim_debugfs_port(efx, debug_entries);
++ /* fall-thru */
++ fail1:
++#endif
++ kfree(efx->phy_data);
++ efx->phy_data = NULL;
++ return rc;
++}
++
++/* Set the lane power down state in the global registers */
++static void txc_glrgs_lane_power(struct efx_nic *efx, int mmd)
++{
++ int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN);
++ int ctl = mdio_clause45_read(efx, efx->mii.phy_id,
++ mmd, TXC_GLRGS_GLCMD);
++
++ if (efx->phy_powered)
++ ctl &= ~pd;
++ else
++ ctl |= pd;
++
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ mmd, TXC_GLRGS_GLCMD, ctl);
++}
++
++/* Set the lane power down state in the analog control registers */
++static void txc_analog_lane_power(struct efx_nic *efx, int mmd)
++{
++ int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
++ | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
++
++ int rxpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
++ | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
++
++ int txctl = mdio_clause45_read(efx, efx->mii.phy_id,
++ mmd, TXC_ALRGS_ATXCTL);
++ int rxctl = mdio_clause45_read(efx, efx->mii.phy_id,
++ mmd, TXC_ALRGS_ARXCTL);
++
++ if (efx->phy_powered) {
++ txctl &= ~txpd;
++ rxctl &= ~rxpd;
++ } else {
++ txctl |= txpd;
++ rxctl |= rxpd;
++ }
++
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ mmd, TXC_ALRGS_ATXCTL, txctl);
++ mdio_clause45_write(efx, efx->mii.phy_id,
++ mmd, TXC_ALRGS_ARXCTL, rxctl);
++}
++
++static void txc_set_power(struct efx_nic *efx)
++{
++ /* According to the data book, all the MMDs can do low power */
++ mdio_clause45_set_mmds_lpower(efx, !efx->phy_powered,
++ TXC_REQUIRED_DEVS);
++
++ /* Global register bank is in PCS, PHY XS. These control the host
++ * side and line side settings respectively. */
++ txc_glrgs_lane_power(efx, MDIO_MMD_PCS);
++ txc_glrgs_lane_power(efx, MDIO_MMD_PHYXS);
++
++ /* Analog register bank in PMA/PMD, PHY XS */
++ txc_analog_lane_power(efx, MDIO_MMD_PMAPMD);
++ txc_analog_lane_power(efx, MDIO_MMD_PHYXS);
++}
++
++
++static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
++{
++ int portid = efx->mii.phy_id;
++ int val = mdio_clause45_read(efx, portid, mmd, TXC_GLRGS_GLCMD);
++ int tries = 50;
++ val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
++ mdio_clause45_write(efx, portid, mmd, TXC_GLRGS_GLCMD, val);
++ while (tries--) {
++ val = mdio_clause45_read(efx, portid, mmd,
++ TXC_GLRGS_GLCMD);
++ if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
++ break;
++ udelay(1);
++ }
++ if (!tries)
++ EFX_INFO(efx, TXCNAME " Logic reset timed out!\n");
++}
++
++
++/* Perform a logic reset. This preserves the configuration registers
++ * and is needed for some configuration changes to take effect */
++static void txc_reset_logic(struct efx_nic *efx)
++{
++ /* The data sheet claims we can do the logic reset on either the
++ * PCS or the PHYXS and the result is a reset of both host- and
++ * line-side logic. */
++ txc_reset_logic_mmd(efx, MDIO_MMD_PCS);
++}
++
++static int txc43128_phy_read_link(struct efx_nic *efx)
++{
++ return mdio_clause45_links_ok(efx, TXC_REQUIRED_DEVS);
++}
++
++static void txc43128_phy_reconfigure(struct efx_nic *efx)
++{
++ struct txc43128_data *phy_data = efx->phy_data;
++ int power_change = (efx->phy_powered != phy_data->phy_powered);
++ int loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS);
++ int disable_change = (efx->tx_disabled != phy_data->tx_disabled);
++
++ if (!phy_data->tx_disabled && efx->tx_disabled) {
++ txc_reset_phy(efx);
++ txc_apply_defaults(efx);
++ falcon_reset_xaui(efx);
++ disable_change = 0;
++ }
++
++ mdio_clause45_transmit_disable(efx, efx->tx_disabled);
++ mdio_clause45_phy_reconfigure(efx);
++ if (power_change)
++ txc_set_power(efx);
++
++ /* The data sheet claims this is required after every reconfiguration
++ * (note at end of 7.1), but we mustn't do it when nothing changes as
++ * it glitches the link, and reconfigure gets called on link change,
++ * so we get an IRQ storm on link up. */
++ if (loop_change || power_change || disable_change)
++ txc_reset_logic(efx);
++
++ phy_data->phy_powered = efx->phy_powered;
++ phy_data->loopback_mode = efx->loopback_mode;
++ phy_data->tx_disabled = efx->tx_disabled;
++ efx->link_up = txc43128_phy_read_link(efx);
++ efx->link_options = GM_LPA_10000FULL;
++}
++
++static void txc43128_phy_fini(struct efx_nic *efx)
++{
++ efx->board_info.blink(efx, 0);
++
++ /* Disable link events */
++ xenpack_disable_lasi_irqs(efx);
++
++#ifdef CONFIG_SFC_DEBUGFS
++ /* Remove the extra debug entries and free data */
++ efx_trim_debugfs_port(efx, debug_entries);
++#endif
++ kfree(efx->phy_data);
++ efx->phy_data = NULL;
++}
++
++/* Periodic callback: this exists mainly to poll link status as we currently
++ * don't use LASI interrupts. Also update the BER counters and poll the lm87 */
++static int txc43128_phy_check_hw(struct efx_nic *efx)
++{
++ struct txc43128_data *data = efx->phy_data;
++#ifdef CONFIG_SFC_DEBUGFS
++ int phy = efx->mii.phy_id;
++ int timer, count, i, mmd;
++#endif
++ int rc = 0;
++ int link_up = txc43128_phy_read_link(efx);
++
++ /* Simulate a PHY event if link state has changed */
++ if (link_up != efx->link_up) {
++ efx->link_up = link_up;
++ efx->mac_op->fake_phy_event(efx);
++ } else if (EFX_WORKAROUND_10934(efx)) {
++ if (link_up || (efx->loopback_mode != LOOPBACK_NONE))
++ data->bug10934_timer = jiffies;
++ else {
++ int delta = jiffies - data->bug10934_timer;
++ if (delta >= BUG10934_RESET_INTERVAL) {
++ data->bug10934_timer = jiffies;
++ txc_reset_logic(efx);
++ }
++ }
++ }
++
++ rc = efx->board_info.monitor(efx);
++ if (rc) {
++ EFX_ERR(efx, "" TXCNAME
++ ": sensor alert! Putting PHY into low power.\n");
++ efx->phy_powered = 0;
++ txc_set_power(efx);
++ }
++
++#ifdef CONFIG_SFC_DEBUGFS
++ /* There are 2 MMDs with RX BER counters: PCS and PHY XS,
++ * which happen to be consecutively numbered */
++ for (mmd = MDIO_MMD_PCS; mmd <= MDIO_MMD_PHYXS; mmd++) {
++ for (i = 0; i < XAUI_NUM_LANES; i++) {
++ timer = mdio_clause45_read(efx, phy, mmd,
++ TXC_RXCTL_BERTMR0 +
++ i * BER_REG_SPACING);
++ count = mdio_clause45_read(efx, phy, mmd,
++ TXC_RXCTL_BERCNT0 +
++ i * BER_REG_SPACING);
++ /* The BER timer counts down in seconds. If it would
++ * expire before the next check_hw, update the stats &
++ * restart the timer (clears the count) */
++ if (timer * HZ < efx_monitor_interval) {
++ /* Record count, allowing for the fact that the
++ * timer may not have reached zero */
++ unsigned ber = (count * BER_INTERVAL) /
++ (BER_INTERVAL - timer * HZ);
++ if (mmd == MDIO_MMD_PCS)
++ data->phy_ber_pcs[i] = ber;
++ else
++ data->phy_ber_phyxs[i] = ber;
++ /* Reprogram the timer */
++ mdio_clause45_write(efx, phy, mmd,
++ TXC_RXCTL_BERTMR0 +
++ i * BER_REG_SPACING,
++ BER_INTERVAL / HZ);
++ }
++ }
++ mmd = (mmd == MDIO_MMD_PCS) ? MDIO_MMD_PHYXS : 0;
++ }
++#endif /* CONFIG_SFC_DEBUGFS */
++ return rc;
++}
++
++struct efx_phy_operations falcon_txc_phy_ops = {
++ .init = txc43128_phy_init,
++ .reconfigure = txc43128_phy_reconfigure,
++ .check_hw = txc43128_phy_check_hw,
++ .fini = txc43128_phy_fini,
++ .clear_interrupt = efx_port_dummy_op_void,
++ .reset_xaui = efx_port_dummy_op_void,
++ .mmds = TXC_REQUIRED_DEVS,
++ .loopbacks = TXC_LOOPBACKS,
++ .startup_loopback = LOOPBACK_PMAPMD,
++};
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/tx.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/tx.h
+--- linux-2.6.18.8/drivers/net/sfc/tx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/tx.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,41 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006: Fen Systems Ltd.
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Initially developed by Michael Brown <mbrown@fensystems.co.uk>
++ * Maintained by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_TX_H
++#define EFX_TX_H
++
++#include "net_driver.h"
++
++int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
++void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
++int efx_init_tx_queue(struct efx_tx_queue *tx_queue);
++void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
++
++int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
++void efx_release_tx_buffers(struct efx_tx_queue *tx_queue);
++
++#endif /* EFX_TX_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/workarounds.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/workarounds.h
+--- linux-2.6.18.8/drivers/net/sfc/workarounds.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/workarounds.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,97 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_WORKAROUNDS_H
++#define EFX_WORKAROUNDS_H
++
++/*
++ * Hardware workarounds.
++ * Bug numbers are from Solarflare's Bugzilla.
++ */
++
++#define EFX_WORKAROUND_ALWAYS(efx) 1
++#define EFX_WORKAROUND_FALCON_A(efx) (FALCON_REV(efx) <= FALCON_REV_A1)
++#define EFX_WORKAROUND_FALCON_B0FPGA(efx) \
++ (FALCON_REV(efx) == FALCON_REV_B0 && !(efx)->is_asic)
++
++/* XAUI resets if link not detected */
++#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
++/* SNAP frames have TOBE_DISC set */
++#define EFX_WORKAROUND_5475 EFX_WORKAROUND_ALWAYS
++/* PHY interrupts can go to the wrong port */
++#define EFX_WORKAROUND_6263 EFX_WORKAROUND_ALWAYS
++/* Reprog PCIe ACK timer to workaround issue in PCIe IP block */
++#define EFX_WORKAROUND_6943 EFX_WORKAROUND_ALWAYS
++/* RX PCIe double split performance issue */
++#define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS
++/* Bit-bashed I2C reads cause performance drop */
++#define EFX_WORKAROUND_7884 EFX_WORKAROUND_ALWAYS
++/* Selftests need to be retried */
++#define EFX_WORKAROUND_8909 EFX_WORKAROUND_ALWAYS
++/* Queued ACKs aren't flushed before L1 entry */
++#define EFX_WORKAROUND_9096 EFX_WORKAROUND_ALWAYS
++/* TX pkt parser problem with <= 16 byte TXes */
++#define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
++/* XGXS and XAUI reset sequencing in SW */
++#define EFX_WORKAROUND_9388 EFX_WORKAROUND_ALWAYS
++/* Low rate CRC errors require XAUI reset */
++#define EFX_WORKAROUND_10750 EFX_WORKAROUND_ALWAYS
++/* TX_EV_PKT_ERR can be caused by a dangling TX descriptor
++ * or a PCIe error (bug 11028) */
++#define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS
++/* CX4 retimer fails to bring link up after reset */
++#define EFX_WORKAROUND_10934 EFX_WORKAROUND_ALWAYS
++/* Transmit flow control may get disabled */
++#define EFX_WORKAROUND_11482 EFX_WORKAROUND_ALWAYS
++/* Flush events can take a very long time to appear */
++#define EFX_WORKAROUND_11557 EFX_WORKAROUND_ALWAYS
++
++/* Spurious parity errors in TSORT buffers */
++#define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A
++/* No unaligned TX over 512 byte boundaries */
++#define EFX_WORKAROUND_5391 EFX_WORKAROUND_FALCON_A
++/* iSCSI parsing errors */
++#define EFX_WORKAROUND_5583 EFX_WORKAROUND_FALCON_A
++/* RX events go missing */
++#define EFX_WORKAROUND_5676 EFX_WORKAROUND_FALCON_A
++/* RX_RESET on A1 */
++#define EFX_WORKAROUND_6555 EFX_WORKAROUND_FALCON_A
++/* Spurious duplicate RX events */
++#define EFX_WORKAROUND_7062 EFX_WORKAROUND_FALCON_A
++/* Increase filter depth to avoid RX_RESET */
++#define EFX_WORKAROUND_7244 EFX_WORKAROUND_FALCON_A
++/* Flushes may never complete */
++#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_A
++/* Leak overlength packets rather than free */
++#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
++
++/* Memory needs clearing at start-of-day */
++#define EFX_WORKAROUND_8202 EFX_WORKAROUND_FALCON_B0FPGA
++/* MAC statistics are transient */
++#define EFX_WORKAROUND_8419 EFX_WORKAROUND_FALCON_B0FPGA
++/* Prefetch watchdog timer may trigger erroneously on busy systems */
++#define EFX_WORKAROUND_9008 EFX_WORKAROUND_FALCON_B0FPGA
++
++#endif /* EFX_WORKAROUNDS_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/xenpack.h linux-2.6.18-xen-3.3.0/drivers/net/sfc/xenpack.h
+--- linux-2.6.18.8/drivers/net/sfc/xenpack.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/xenpack.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,80 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef EFX_XENPACK_H
++#define EFX_XENPACK_H
++
++/* Exported functions from Xenpack standard PHY control */
++
++#include "mdio_10g.h"
++
++/****************************************************************************/
++/* XENPACK MDIO register extensions */
++#define MDIO_XP_LASI_RX_CTRL (0x9000)
++#define MDIO_XP_LASI_TX_CTRL (0x9001)
++#define MDIO_XP_LASI_CTRL (0x9002)
++#define MDIO_XP_LASI_RX_STAT (0x9003)
++#define MDIO_XP_LASI_TX_STAT (0x9004)
++#define MDIO_XP_LASI_STAT (0x9005)
++
++/* Control/Status bits */
++#define XP_LASI_LS_ALARM (1 << 0)
++#define XP_LASI_TX_ALARM (1 << 1)
++#define XP_LASI_RX_ALARM (1 << 2)
++/* These two are Quake vendor extensions to the standard XENPACK defines */
++#define XP_LASI_LS_INTB (1 << 3)
++#define XP_LASI_TEST (1 << 7)
++
++/* Enable LASI interrupts for PHY */
++static inline void xenpack_enable_lasi_irqs(struct efx_nic *efx)
++{
++ int reg;
++ int phy_id = efx->mii.phy_id;
++ /* Read to clear LASI status register */
++ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
++ MDIO_XP_LASI_STAT);
++
++ /* Enable LASI interrupts from PMA/PMD */
++ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
++ MDIO_XP_LASI_CTRL, XP_LASI_LS_ALARM);
++}
++
++/* Read the LASI interrupt status to clear the interrupt. */
++static inline int xenpack_clear_lasi_irqs(struct efx_nic *efx)
++{
++ /* Read to clear link status alarm */
++ return mdio_clause45_read(efx, efx->mii.phy_id,
++ MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT);
++}
++
++/* Turn off LASI interrupts */
++static inline void xenpack_disable_lasi_irqs(struct efx_nic *efx)
++{
++ /* Turn LASI interrupts off */
++ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
++ MDIO_XP_LASI_CTRL, 0);
++}
++
++#endif /* EFX_XENPACK_H */
+diff -rpuN linux-2.6.18.8/drivers/net/sfc/xfp_phy.c linux-2.6.18-xen-3.3.0/drivers/net/sfc/xfp_phy.c
+--- linux-2.6.18.8/drivers/net/sfc/xfp_phy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/net/sfc/xfp_phy.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,206 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++/*
++ * Driver for XFP optical PHYs (plus some support specific to the Quake 2032)
++ * See www.amcc.com for details (search for qt2032)
++ */
++
++#include <linux/timer.h>
++#include <linux/delay.h>
++#include "efx.h"
++#include "gmii.h"
++#include "mdio_10g.h"
++#include "xenpack.h"
++#include "phy.h"
++
++#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PCS | \
++ MDIO_MMDREG_DEVS0_PMAPMD | \
++ MDIO_MMDREG_DEVS0_PHYXS)
++
++#define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \
++ (1 << LOOPBACK_PMAPMD) | \
++ (1 << LOOPBACK_NETWORK))
++
++/****************************************************************************/
++/* Quake-specific MDIO registers */
++#define MDIO_QUAKE_LED0_REG (0xD006)
++
++
++void xfp_set_led(struct efx_nic *p, int led, int mode)
++{
++ int addr = MDIO_QUAKE_LED0_REG + led;
++ mdio_clause45_write(p, p->mii.phy_id, MDIO_MMD_PMAPMD, addr,
++ mode);
++}
++
++struct xfp_phy_data {
++ int phy_powered;
++ int tx_disabled;
++};
++
++
++#define XFP_MAX_RESET_TIME 500
++#define XFP_RESET_WAIT 10
++
++/* Reset the PHYXS MMD. This is documented (for the Quake PHY) as doing
++ * a complete soft reset.
++ */
++static int xfp_reset_phy(struct efx_nic *efx)
++{
++ int rc;
++
++ rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PHYXS,
++ XFP_MAX_RESET_TIME / XFP_RESET_WAIT,
++ XFP_RESET_WAIT);
++ if (rc < 0)
++ goto fail;
++
++ /* Wait 250ms for the PHY to complete bootup */
++ msleep(250);
++
++ /* Check that all the MMDs we expect are present and responding. We
++ * expect faults on some if the link is down, but not on the PHY XS */
++ rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS,
++ MDIO_MMDREG_DEVS0_PHYXS);
++ if (rc < 0)
++ goto fail;
++
++ efx->board_info.init_leds(efx);
++
++ return rc;
++
++ fail:
++ EFX_ERR(efx, "XFP: reset timed out!\n");
++ return rc;
++}
++
++
++static int xfp_phy_init(struct efx_nic *efx)
++{
++ struct xfp_phy_data *phy_data;
++ u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS);
++ int rc;
++
++ phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL);
++ efx->phy_data = (void *) phy_data;
++
++ EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision"
++ " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid),
++ MDIO_ID_REV(devid));
++
++ phy_data->phy_powered = efx->phy_powered;
++ phy_data->tx_disabled = efx->tx_disabled;
++
++ rc = xfp_reset_phy(efx);
++ if (rc < 0)
++ goto fail;
++
++ EFX_INFO(efx, "XFP: PHY init %s.\n",
++ rc ? "failed" : "successful");
++ return 0;
++
++ fail:
++ kfree(efx->phy_data);
++ efx->phy_data = NULL;
++ return rc;
++}
++
++static void xfp_phy_clear_interrupt(struct efx_nic *efx)
++{
++ xenpack_clear_lasi_irqs(efx);
++}
++
++static int xfp_link_ok(struct efx_nic *efx)
++{
++ return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS);
++}
++
++static int xfp_phy_check_hw(struct efx_nic *efx)
++{
++ int rc = 0;
++ int link_up = xfp_link_ok(efx);
++ /* Simulate a PHY event if link state has changed */
++ if (link_up != efx->link_up) {
++ efx->link_up = link_up;
++ efx->mac_op->fake_phy_event(efx);
++ }
++
++ rc = efx->board_info.monitor(efx);
++ if (rc) {
++ EFX_ERR(efx, ": XFP sensor alert! Putting PHY into "
++ "low power.\n");
++ efx->phy_powered = 0;
++
++ mdio_clause45_set_mmds_lpower(efx, 1, XFP_REQUIRED_DEVS);
++ }
++
++ return rc;
++}
++
++static void xfp_phy_reconfigure(struct efx_nic *efx)
++{
++ struct xfp_phy_data *phy_data = efx->phy_data;
++
++ /* Reset the PHY when moving from transmitter off or powered off,
++ * to transmitter on and powered on */
++ if ((efx->phy_powered && !efx->tx_disabled) &&
++ (!phy_data->phy_powered || phy_data->tx_disabled))
++ xfp_reset_phy(efx);
++
++ mdio_clause45_transmit_disable(efx, efx->tx_disabled);
++ mdio_clause45_set_mmds_lpower(efx, !efx->phy_powered,
++ XFP_REQUIRED_DEVS);
++ mdio_clause45_phy_reconfigure(efx);
++
++ phy_data->tx_disabled = efx->tx_disabled;
++ phy_data->phy_powered = efx->phy_powered;
++ efx->link_up = xfp_link_ok(efx);
++ efx->link_options = GM_LPA_10000FULL;
++}
++
++
++static void xfp_phy_fini(struct efx_nic *efx)
++{
++ /* Clobber the LED if it was blinking */
++ efx->board_info.blink(efx, 0);
++
++ /* Free the context block */
++ kfree(efx->phy_data);
++ efx->phy_data = NULL;
++}
++
++struct efx_phy_operations falcon_xfp_phy_ops = {
++ .init = xfp_phy_init,
++ .reconfigure = xfp_phy_reconfigure,
++ .check_hw = xfp_phy_check_hw,
++ .fini = xfp_phy_fini,
++ .clear_interrupt = xfp_phy_clear_interrupt,
++ .reset_xaui = efx_port_dummy_op_void,
++ .mmds = XFP_REQUIRED_DEVS,
++ .loopbacks = XFP_LOOPBACKS,
++ /* No loopback appears to be reliable enough for self-test
++ * operation. So don't do it. */
++ .startup_loopback = LOOPBACK_PCS,
++};
+diff -rpuN linux-2.6.18.8/drivers/oprofile/buffer_sync.c linux-2.6.18-xen-3.3.0/drivers/oprofile/buffer_sync.c
+--- linux-2.6.18.8/drivers/oprofile/buffer_sync.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/oprofile/buffer_sync.c 2008-08-21 11:36:07.000000000 +0200
@@ -6,6 +6,10 @@
*
* @author John Levon <levon@movementarian.org>
@@ -76411,9 +120360,9 @@ diff -rpuN linux-2.6.18.8/drivers/oprofile/buffer_sync.c linux-2.6.18-xen-3.2.0/
mark_done(cpu);
mutex_unlock(&buffer_mutex);
-diff -rpuN linux-2.6.18.8/drivers/oprofile/cpu_buffer.c linux-2.6.18-xen-3.2.0/drivers/oprofile/cpu_buffer.c
---- linux-2.6.18.8/drivers/oprofile/cpu_buffer.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/oprofile/cpu_buffer.c 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/oprofile/cpu_buffer.c linux-2.6.18-xen-3.3.0/drivers/oprofile/cpu_buffer.c
+--- linux-2.6.18.8/drivers/oprofile/cpu_buffer.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/oprofile/cpu_buffer.c 2008-08-21 11:36:07.000000000 +0200
@@ -6,6 +6,10 @@
*
* @author John Levon <levon@movementarian.org>
@@ -76522,9 +120471,9 @@ diff -rpuN linux-2.6.18.8/drivers/oprofile/cpu_buffer.c linux-2.6.18-xen-3.2.0/d
/*
* This serves to avoid cpu buffer overflow, and makes sure
* the task mortuary progresses
-diff -rpuN linux-2.6.18.8/drivers/oprofile/cpu_buffer.h linux-2.6.18-xen-3.2.0/drivers/oprofile/cpu_buffer.h
---- linux-2.6.18.8/drivers/oprofile/cpu_buffer.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/oprofile/cpu_buffer.h 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/oprofile/cpu_buffer.h linux-2.6.18-xen-3.3.0/drivers/oprofile/cpu_buffer.h
+--- linux-2.6.18.8/drivers/oprofile/cpu_buffer.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/oprofile/cpu_buffer.h 2008-08-21 11:36:07.000000000 +0200
@@ -36,7 +36,7 @@ struct oprofile_cpu_buffer {
volatile unsigned long tail_pos;
unsigned long buffer_size;
@@ -76547,9 +120496,9 @@ diff -rpuN linux-2.6.18.8/drivers/oprofile/cpu_buffer.h linux-2.6.18-xen-3.2.0/d
+#define CPU_DOMAIN_SWITCH 4
#endif /* OPROFILE_CPU_BUFFER_H */
-diff -rpuN linux-2.6.18.8/drivers/oprofile/event_buffer.h linux-2.6.18-xen-3.2.0/drivers/oprofile/event_buffer.h
---- linux-2.6.18.8/drivers/oprofile/event_buffer.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/oprofile/event_buffer.h 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/oprofile/event_buffer.h linux-2.6.18-xen-3.3.0/drivers/oprofile/event_buffer.h
+--- linux-2.6.18.8/drivers/oprofile/event_buffer.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/oprofile/event_buffer.h 2008-08-21 11:36:07.000000000 +0200
@@ -29,15 +29,20 @@ void wake_up_buffer_waiter(void);
#define CPU_SWITCH_CODE 2
#define COOKIE_SWITCH_CODE 3
@@ -76572,9 +120521,9 @@ diff -rpuN linux-2.6.18.8/drivers/oprofile/event_buffer.h linux-2.6.18-xen-3.2.0
/* add data to the event buffer */
void add_event_entry(unsigned long data);
-diff -rpuN linux-2.6.18.8/drivers/oprofile/oprof.c linux-2.6.18-xen-3.2.0/drivers/oprofile/oprof.c
---- linux-2.6.18.8/drivers/oprofile/oprof.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/oprofile/oprof.c 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/oprofile/oprof.c linux-2.6.18-xen-3.3.0/drivers/oprofile/oprof.c
+--- linux-2.6.18.8/drivers/oprofile/oprof.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/oprofile/oprof.c 2008-08-21 11:36:07.000000000 +0200
@@ -5,6 +5,10 @@
* @remark Read the file COPYING
*
@@ -76628,9 +120577,9 @@ diff -rpuN linux-2.6.18.8/drivers/oprofile/oprof.c linux-2.6.18-xen-3.2.0/driver
int oprofile_setup(void)
{
int err;
-diff -rpuN linux-2.6.18.8/drivers/oprofile/oprof.h linux-2.6.18-xen-3.2.0/drivers/oprofile/oprof.h
---- linux-2.6.18.8/drivers/oprofile/oprof.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/oprofile/oprof.h 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/oprofile/oprof.h linux-2.6.18-xen-3.3.0/drivers/oprofile/oprof.h
+--- linux-2.6.18.8/drivers/oprofile/oprof.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/oprofile/oprof.h 2008-08-21 11:36:07.000000000 +0200
@@ -35,5 +35,8 @@ void oprofile_create_files(struct super_
void oprofile_timer_init(struct oprofile_operations * ops);
@@ -76640,9 +120589,9 @@ diff -rpuN linux-2.6.18.8/drivers/oprofile/oprof.h linux-2.6.18-xen-3.2.0/driver
+int oprofile_set_passive(int passive_domains[], unsigned int pdomains);
#endif /* OPROF_H */
-diff -rpuN linux-2.6.18.8/drivers/oprofile/oprofile_files.c linux-2.6.18-xen-3.2.0/drivers/oprofile/oprofile_files.c
---- linux-2.6.18.8/drivers/oprofile/oprofile_files.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/oprofile/oprofile_files.c 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/oprofile/oprofile_files.c linux-2.6.18-xen-3.3.0/drivers/oprofile/oprofile_files.c
+--- linux-2.6.18.8/drivers/oprofile/oprofile_files.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/oprofile/oprofile_files.c 2008-08-21 11:36:07.000000000 +0200
@@ -5,15 +5,21 @@
* @remark Read the file COPYING
*
@@ -76870,20 +120819,9 @@ diff -rpuN linux-2.6.18.8/drivers/oprofile/oprofile_files.c linux-2.6.18-xen-3.2
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 -rpuN linux-2.6.18.8/drivers/pci/Kconfig linux-2.6.18-xen-3.2.0/drivers/pci/Kconfig
---- linux-2.6.18.8/drivers/pci/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/pci/Kconfig 2008-02-15 16:22:00.000000000 -0800
-@@ -5,6 +5,7 @@ config PCI_MSI
- bool "Message Signaled Interrupts (MSI and MSI-X)"
- depends on PCI
- depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
-+ depends on !XEN
- help
- This allows device drivers to enable MSI (Message Signaled
- Interrupts). Message Signaled Interrupts enable a device to
-diff -rpuN linux-2.6.18.8/drivers/pci/bus.c linux-2.6.18-xen-3.2.0/drivers/pci/bus.c
---- linux-2.6.18.8/drivers/pci/bus.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/pci/bus.c 2008-02-15 16:22:00.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/pci/bus.c linux-2.6.18-xen-3.3.0/drivers/pci/bus.c
+--- linux-2.6.18.8/drivers/pci/bus.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/pci/bus.c 2008-08-21 11:36:07.000000000 +0200
@@ -17,6 +17,8 @@
#include "pci.h"
@@ -76905,9 +120843,759 @@ diff -rpuN linux-2.6.18.8/drivers/pci/bus.c linux-2.6.18-xen-3.2.0/drivers/pci/b
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
struct resource *r = bus->resource[i];
if (!r)
-diff -rpuN linux-2.6.18.8/drivers/pci/quirks.c linux-2.6.18-xen-3.2.0/drivers/pci/quirks.c
---- linux-2.6.18.8/drivers/pci/quirks.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/pci/quirks.c 2008-02-15 16:22:01.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/pci/msi-xen.c linux-2.6.18-xen-3.3.0/drivers/pci/msi-xen.c
+--- linux-2.6.18.8/drivers/pci/msi-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/pci/msi-xen.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,746 @@
++/*
++ * File: msi.c
++ * Purpose: PCI Message Signaled Interrupt (MSI)
++ *
++ * Copyright (C) 2003-2004 Intel
++ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
++ */
++
++#include <linux/mm.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/smp_lock.h>
++#include <linux/pci.h>
++#include <linux/proc_fs.h>
++
++#include <asm/errno.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++
++#include "pci.h"
++#include "msi.h"
++
++static int pci_msi_enable = 1;
++
++static struct msi_ops *msi_ops;
++
++int msi_register(struct msi_ops *ops)
++{
++ msi_ops = ops;
++ return 0;
++}
++
++static LIST_HEAD(msi_dev_head);
++DEFINE_SPINLOCK(msi_dev_lock);
++
++struct msi_dev_list {
++ struct pci_dev *dev;
++ struct list_head list;
++ spinlock_t pirq_list_lock;
++ struct list_head pirq_list_head;
++};
++
++struct msi_pirq_entry {
++ struct list_head list;
++ int pirq;
++ int entry_nr;
++};
++
++static struct msi_dev_list *get_msi_dev_pirq_list(struct pci_dev *dev)
++{
++ struct msi_dev_list *msi_dev_list, *ret = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&msi_dev_lock, flags);
++
++ list_for_each_entry(msi_dev_list, &msi_dev_head, list)
++ if ( msi_dev_list->dev == dev )
++ ret = msi_dev_list;
++
++ if ( ret ) {
++ spin_unlock_irqrestore(&msi_dev_lock, flags);
++ return ret;
++ }
++
++ /* Has not allocate msi_dev until now. */
++ ret = kmalloc(sizeof(struct msi_dev_list), GFP_ATOMIC);
++
++ /* Failed to allocate msi_dev structure */
++ if ( !ret ) {
++ spin_unlock_irqrestore(&msi_dev_lock, flags);
++ return NULL;
++ }
++
++ spin_lock_init(&ret->pirq_list_lock);
++ INIT_LIST_HEAD(&ret->pirq_list_head);
++ list_add_tail(&ret->list, &msi_dev_head);
++ spin_unlock_irqrestore(&msi_dev_lock, flags);
++ return ret;
++}
++
++static int attach_pirq_entry(int pirq, int entry_nr,
++ struct msi_dev_list *msi_dev_entry)
++{
++ struct msi_pirq_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
++ unsigned long flags;
++
++ if (!entry)
++ return -ENOMEM;
++ entry->pirq = pirq;
++ entry->entry_nr = entry_nr;
++ spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
++ list_add_tail(&entry->list, &msi_dev_entry->pirq_list_head);
++ spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
++ return 0;
++}
++
++static void detach_pirq_entry(int entry_nr,
++ struct msi_dev_list *msi_dev_entry)
++{
++ unsigned long flags;
++ struct msi_pirq_entry *pirq_entry;
++
++ list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
++ if (pirq_entry->entry_nr == entry_nr) {
++ spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
++ list_del(&pirq_entry->list);
++ spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
++ kfree(pirq_entry);
++ return;
++ }
++ }
++}
++
++/*
++ * pciback will provide device's owner
++ */
++static int (*get_owner)(struct pci_dev *dev);
++
++int register_msi_get_owner(int (*func)(struct pci_dev *dev))
++{
++ if (get_owner) {
++ printk(KERN_WARNING "register msi_get_owner again\n");
++ return -EEXIST;
++ }
++ get_owner = func;
++ return 0;
++}
++
++int unregister_msi_get_owner(int (*func)(struct pci_dev *dev))
++{
++ if (get_owner != func)
++ return -EINVAL;
++ get_owner = NULL;
++ return 0;
++}
++
++static int msi_get_dev_owner(struct pci_dev *dev)
++{
++ int owner;
++
++ BUG_ON(!is_initial_xendomain());
++ if (get_owner && (owner = get_owner(dev)) >= 0) {
++ printk(KERN_INFO "get owner for dev %x get %x \n",
++ dev->devfn, owner);
++ return owner;
++ }
++
++ return DOMID_SELF;
++}
++
++static int msi_unmap_pirq(struct pci_dev *dev, int pirq)
++{
++ struct physdev_unmap_pirq unmap;
++ int rc;
++
++ unmap.domid = msi_get_dev_owner(dev);
++ unmap.pirq = pirq;
++
++ if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
++ printk(KERN_WARNING "unmap irq %x failed\n", pirq);
++
++ if (rc < 0)
++ return rc;
++ return 0;
++}
++
++static u64 find_table_base(struct pci_dev *dev, int pos)
++{
++ u8 bar;
++ u32 reg;
++ unsigned long flags;
++
++ pci_read_config_dword(dev, msix_table_offset_reg(pos), &reg);
++ bar = reg & PCI_MSIX_FLAGS_BIRMASK;
++
++ flags = pci_resource_flags(dev, bar);
++ if (flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET | IORESOURCE_BUSY))
++ return 0;
++
++ return pci_resource_start(dev, bar);
++}
++
++/*
++ * Protected by msi_lock
++ */
++static int msi_map_pirq_to_vector(struct pci_dev *dev, int pirq,
++ int entry_nr, u64 table_base)
++{
++ struct physdev_map_pirq map_irq;
++ int rc;
++ domid_t domid = DOMID_SELF;
++
++ domid = msi_get_dev_owner(dev);
++
++ map_irq.domid = domid;
++ map_irq.type = MAP_PIRQ_TYPE_MSI;
++ map_irq.index = -1;
++ map_irq.pirq = pirq;
++ map_irq.bus = dev->bus->number;
++ map_irq.devfn = dev->devfn;
++ map_irq.entry_nr = entry_nr;
++ map_irq.table_base = table_base;
++
++ if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq)))
++ printk(KERN_WARNING "map irq failed\n");
++
++ if (rc < 0)
++ return rc;
++
++ return map_irq.pirq;
++}
++
++static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
++{
++ return msi_map_pirq_to_vector(dev, -1, entry_nr, table_base);
++}
++
++static int msi_init(void)
++{
++ static int status = 0;
++
++ if (pci_msi_quirk) {
++ pci_msi_enable = 0;
++ printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n");
++ status = -EINVAL;
++ }
++
++ return status;
++}
++
++void pci_scan_msi_device(struct pci_dev *dev) { }
++
++void disable_msi_mode(struct pci_dev *dev, int pos, int type)
++{
++ u16 control;
++
++ pci_read_config_word(dev, msi_control_reg(pos), &control);
++ if (type == PCI_CAP_ID_MSI) {
++ /* Set enabled bits to single MSI & enable MSI_enable bit */
++ msi_disable(control);
++ pci_write_config_word(dev, msi_control_reg(pos), control);
++ dev->msi_enabled = 0;
++ } else {
++ msix_disable(control);
++ pci_write_config_word(dev, msi_control_reg(pos), control);
++ dev->msix_enabled = 0;
++ }
++ if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
++ /* PCI Express Endpoint device detected */
++ pci_intx(dev, 1); /* enable intx */
++ }
++}
++
++static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
++{
++ u16 control;
++
++ pci_read_config_word(dev, msi_control_reg(pos), &control);
++ if (type == PCI_CAP_ID_MSI) {
++ /* Set enabled bits to single MSI & enable MSI_enable bit */
++ msi_enable(control, 1);
++ pci_write_config_word(dev, msi_control_reg(pos), control);
++ dev->msi_enabled = 1;
++ } else {
++ msix_enable(control);
++ pci_write_config_word(dev, msi_control_reg(pos), control);
++ dev->msix_enabled = 1;
++ }
++ if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
++ /* PCI Express Endpoint device detected */
++ pci_intx(dev, 0); /* disable intx */
++ }
++}
++
++#ifdef CONFIG_PM
++int pci_save_msi_state(struct pci_dev *dev)
++{
++ int pos;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++ if (pos <= 0 || dev->no_msi)
++ return 0;
++
++ if (!dev->msi_enabled)
++ return 0;
++
++ /* Restore dev->irq to its default pin-assertion vector */
++ msi_unmap_pirq(dev, dev->irq);
++ /* Disable MSI mode */
++ disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++ /* Set the flags for use of restore */
++ dev->msi_enabled = 1;
++ return 0;
++}
++
++void pci_restore_msi_state(struct pci_dev *dev)
++{
++ int pos, pirq;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++ if (pos <= 0)
++ return;
++
++ if (!dev->msi_enabled)
++ return;
++
++ pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 0);
++ if (pirq < 0)
++ return;
++ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++}
++
++int pci_save_msix_state(struct pci_dev *dev)
++{
++ int pos;
++ unsigned long flags;
++ struct msi_dev_list *msi_dev_entry;
++ struct msi_pirq_entry *pirq_entry, *tmp;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++ if (pos <= 0 || dev->no_msi)
++ return 0;
++
++ /* save the capability */
++ if (!dev->msix_enabled)
++ return 0;
++
++ msi_dev_entry = get_msi_dev_pirq_list(dev);
++
++ spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
++ list_for_each_entry_safe(pirq_entry, tmp,
++ &msi_dev_entry->pirq_list_head, list)
++ msi_unmap_pirq(dev, pirq_entry->pirq);
++ spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
++
++ disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
++ /* Set the flags for use of restore */
++ dev->msix_enabled = 1;
++
++ return 0;
++}
++
++void pci_restore_msix_state(struct pci_dev *dev)
++{
++ int pos;
++ unsigned long flags;
++ u64 table_base;
++ struct msi_dev_list *msi_dev_entry;
++ struct msi_pirq_entry *pirq_entry, *tmp;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++ if (pos <= 0)
++ return;
++
++ if (!dev->msix_enabled)
++ return;
++
++ msi_dev_entry = get_msi_dev_pirq_list(dev);
++ table_base = find_table_base(dev, pos);
++ if (!table_base)
++ return;
++
++ spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
++ list_for_each_entry_safe(pirq_entry, tmp,
++ &msi_dev_entry->pirq_list_head, list)
++ msi_map_pirq_to_vector(dev, pirq_entry->pirq,
++ pirq_entry->entry_nr, table_base);
++ spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
++
++ enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
++}
++#endif
++
++/**
++ * msi_capability_init - configure device's MSI capability structure
++ * @dev: pointer to the pci_dev data structure of MSI device function
++ *
++ * Setup the MSI capability structure of device function with a single
++ * MSI vector, regardless of device function is capable of handling
++ * multiple messages. A return of zero indicates the successful setup
++ * of an entry zero with the new MSI vector or non-zero for otherwise.
++ **/
++static int msi_capability_init(struct pci_dev *dev)
++{
++ int pos, pirq;
++ u16 control;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++ pci_read_config_word(dev, msi_control_reg(pos), &control);
++
++ pirq = msi_map_vector(dev, 0, 0);
++ if (pirq < 0)
++ return -EBUSY;
++
++ dev->irq = pirq;
++ /* Set MSI enabled bits */
++ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++ dev->msi_enabled = 1;
++
++ return 0;
++}
++
++/**
++ * msix_capability_init - configure device's MSI-X capability
++ * @dev: pointer to the pci_dev data structure of MSI-X device function
++ * @entries: pointer to an array of struct msix_entry entries
++ * @nvec: number of @entries
++ *
++ * Setup the MSI-X capability structure of device function with a
++ * single MSI-X vector. A return of zero indicates the successful setup of
++ * requested MSI-X entries with allocated vectors or non-zero for otherwise.
++ **/
++static int msix_capability_init(struct pci_dev *dev,
++ struct msix_entry *entries, int nvec)
++{
++ u64 table_base;
++ int pirq, i, j, mapped, pos;
++ struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
++ struct msi_pirq_entry *pirq_entry;
++
++ if (!msi_dev_entry)
++ return -ENOMEM;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++ table_base = find_table_base(dev, pos);
++ if (!table_base)
++ return -ENODEV;
++
++ /* MSI-X Table Initialization */
++ for (i = 0; i < nvec; i++) {
++ mapped = 0;
++ list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
++ if (pirq_entry->entry_nr == entries[i].entry) {
++ printk(KERN_WARNING "msix entry %d for dev %02x:%02x:%01x are \
++ not freed before acquire again.\n", entries[i].entry,
++ dev->bus->number, PCI_SLOT(dev->devfn),
++ PCI_FUNC(dev->devfn));
++ (entries + i)->vector = pirq_entry->pirq;
++ mapped = 1;
++ break;
++ }
++ }
++ if (mapped)
++ continue;
++ pirq = msi_map_vector(dev, entries[i].entry, table_base);
++ if (pirq < 0)
++ break;
++ attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
++ (entries + i)->vector = pirq;
++ }
++
++ if (i != nvec) {
++ for (j = --i; j >= 0; j--) {
++ msi_unmap_pirq(dev, entries[j].vector);
++ detach_pirq_entry(entries[j].entry, msi_dev_entry);
++ entries[j].vector = 0;
++ }
++ return -EBUSY;
++ }
++
++ enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
++ dev->msix_enabled = 1;
++
++ return 0;
++}
++
++/**
++ * pci_enable_msi - configure device's MSI capability structure
++ * @dev: pointer to the pci_dev data structure of MSI device function
++ *
++ * Setup the MSI capability structure of device function with
++ * a single MSI vector upon its software driver call to request for
++ * MSI mode enabled on its hardware device function. A return of zero
++ * indicates the successful setup of an entry zero with the new MSI
++ * vector or non-zero for otherwise.
++ **/
++extern int pci_frontend_enable_msi(struct pci_dev *dev);
++int pci_enable_msi(struct pci_dev* dev)
++{
++ struct pci_bus *bus;
++ int pos, temp, status = -EINVAL;
++
++ if (!pci_msi_enable || !dev)
++ return status;
++
++ if (dev->no_msi)
++ return status;
++
++ for (bus = dev->bus; bus; bus = bus->parent)
++ if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
++ return -EINVAL;
++
++ status = msi_init();
++ if (status < 0)
++ return status;
++
++#ifdef CONFIG_XEN_PCIDEV_FRONTEND
++ if (!is_initial_xendomain())
++ {
++ int ret;
++
++ temp = dev->irq;
++ ret = pci_frontend_enable_msi(dev);
++ if (ret)
++ return ret;
++
++ dev->irq_old = temp;
++
++ return ret;
++ }
++#endif
++
++ temp = dev->irq;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++ if (!pos)
++ return -EINVAL;
++
++ /* Check whether driver already requested for MSI-X vectors */
++ if (dev->msix_enabled) {
++ printk(KERN_INFO "PCI: %s: Can't enable MSI. "
++ "Device already has MSI-X vectors assigned\n",
++ pci_name(dev));
++ dev->irq = temp;
++ return -EINVAL;
++ }
++
++ status = msi_capability_init(dev);
++ if ( !status )
++ dev->irq_old = temp;
++ else
++ dev->irq = temp;
++
++ return status;
++}
++
++extern void pci_frontend_disable_msi(struct pci_dev* dev);
++void pci_disable_msi(struct pci_dev* dev)
++{
++ int pos;
++ int pirq;
++
++ if (!pci_msi_enable)
++ return;
++ if (!dev)
++ return;
++
++#ifdef CONFIG_XEN_PCIDEV_FRONTEND
++ if (!is_initial_xendomain()) {
++ pci_frontend_disable_msi(dev);
++ dev->irq = dev->irq_old;
++ return;
++ }
++#endif
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++ if (!pos)
++ return;
++
++ pirq = dev->irq;
++ /* Restore dev->irq to its default pin-assertion vector */
++ dev->irq = dev->irq_old;
++ msi_unmap_pirq(dev, pirq);
++
++ /* Disable MSI mode */
++ disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++}
++
++/**
++ * pci_enable_msix - configure device's MSI-X capability structure
++ * @dev: pointer to the pci_dev data structure of MSI-X device function
++ * @entries: pointer to an array of MSI-X entries
++ * @nvec: number of MSI-X vectors requested for allocation by device driver
++ *
++ * Setup the MSI-X capability structure of device function with the number
++ * of requested vectors upon its software driver call to request for
++ * MSI-X mode enabled on its hardware device function. A return of zero
++ * indicates the successful configuration of MSI-X capability structure
++ * with new allocated MSI-X vectors. A return of < 0 indicates a failure.
++ * Or a return of > 0 indicates that driver request is exceeding the number
++ * of vectors available. Driver should use the returned value to re-send
++ * its request.
++ **/
++extern int pci_frontend_enable_msix(struct pci_dev *dev,
++ struct msix_entry *entries, int nvec);
++int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
++{
++ struct pci_bus *bus;
++ int status, pos, nr_entries;
++ int i, j, temp;
++ u16 control;
++
++ if (!pci_msi_enable || !dev || !entries)
++ return -EINVAL;
++
++ if (dev->no_msi)
++ return -EINVAL;
++
++ for (bus = dev->bus; bus; bus = bus->parent)
++ if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
++ return -EINVAL;
++
++#ifdef CONFIG_XEN_PCIDEV_FRONTEND
++ if (!is_initial_xendomain()) {
++ int ret;
++
++ ret = pci_frontend_enable_msix(dev, entries, nvec);
++ if (ret) {
++ printk("get %x from pci_frontend_enable_msix\n", ret);
++ return ret;
++ }
++
++ return 0;
++ }
++#endif
++
++ status = msi_init();
++ if (status < 0)
++ return status;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++ if (!pos)
++ return -EINVAL;
++
++ pci_read_config_word(dev, msi_control_reg(pos), &control);
++ nr_entries = multi_msix_capable(control);
++ if (nvec > nr_entries)
++ return -EINVAL;
++
++ /* Check for any invalid entries */
++ for (i = 0; i < nvec; i++) {
++ if (entries[i].entry >= nr_entries)
++ return -EINVAL; /* invalid entry */
++ for (j = i + 1; j < nvec; j++) {
++ if (entries[i].entry == entries[j].entry)
++ return -EINVAL; /* duplicate entry */
++ }
++ }
++
++ temp = dev->irq;
++ /* Check whether driver already requested for MSI vector */
++ if (dev->msi_enabled) {
++ printk(KERN_INFO "PCI: %s: Can't enable MSI-X. "
++ "Device already has an MSI vector assigned\n",
++ pci_name(dev));
++ dev->irq = temp;
++ return -EINVAL;
++ }
++
++ status = msix_capability_init(dev, entries, nvec);
++
++ if ( !status )
++ dev->irq_old = temp;
++ else
++ dev->irq = temp;
++
++ return status;
++}
++
++extern void pci_frontend_disable_msix(struct pci_dev* dev);
++void pci_disable_msix(struct pci_dev* dev)
++{
++ int pos;
++ u16 control;
++
++
++ if (!pci_msi_enable)
++ return;
++ if (!dev)
++ return;
++
++#ifdef CONFIG_XEN_PCIDEV_FRONTEND
++ if (!is_initial_xendomain()) {
++ pci_frontend_disable_msix(dev);
++ dev->irq = dev->irq_old;
++ return;
++ }
++#endif
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++ if (!pos)
++ return;
++
++ pci_read_config_word(dev, msi_control_reg(pos), &control);
++ if (!(control & PCI_MSIX_FLAGS_ENABLE))
++ return;
++
++ msi_remove_pci_irq_vectors(dev);
++
++ /* Disable MSI mode */
++ disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
++}
++
++/**
++ * msi_remove_pci_irq_vectors - reclaim MSI(X) vectors to unused state
++ * @dev: pointer to the pci_dev data structure of MSI(X) device function
++ *
++ * Being called during hotplug remove, from which the device function
++ * is hot-removed. All previous assigned MSI/MSI-X vectors, if
++ * allocated for this device function, are reclaimed to unused state,
++ * which may be used later on.
++ **/
++void msi_remove_pci_irq_vectors(struct pci_dev* dev)
++{
++ unsigned long flags;
++ struct msi_dev_list *msi_dev_entry;
++ struct msi_pirq_entry *pirq_entry, *tmp;
++
++ if (!pci_msi_enable || !dev)
++ return;
++
++ msi_dev_entry = get_msi_dev_pirq_list(dev);
++
++ spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
++ if (!list_empty(&msi_dev_entry->pirq_list_head))
++ {
++ printk(KERN_WARNING "msix pirqs for dev %02x:%02x:%01x are not freed \
++ before acquire again.\n", dev->bus->number, PCI_SLOT(dev->devfn),
++ PCI_FUNC(dev->devfn));
++ list_for_each_entry_safe(pirq_entry, tmp,
++ &msi_dev_entry->pirq_list_head, list) {
++ msi_unmap_pirq(dev, pirq_entry->pirq);
++ list_del(&pirq_entry->list);
++ kfree(pirq_entry);
++ }
++ }
++ spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
++ dev->irq = dev->irq_old;
++}
++
++void pci_no_msi(void)
++{
++ pci_msi_enable = 0;
++}
++
++EXPORT_SYMBOL(pci_enable_msi);
++EXPORT_SYMBOL(pci_disable_msi);
++EXPORT_SYMBOL(pci_enable_msix);
++EXPORT_SYMBOL(pci_disable_msix);
++#ifdef CONFIG_XEN
++EXPORT_SYMBOL(register_msi_get_owner);
++EXPORT_SYMBOL(unregister_msi_get_owner);
++#endif
++
+diff -rpuN linux-2.6.18.8/drivers/pci/quirks.c linux-2.6.18-xen-3.3.0/drivers/pci/quirks.c
+--- linux-2.6.18.8/drivers/pci/quirks.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/pci/quirks.c 2008-08-21 11:36:07.000000000 +0200
@@ -23,6 +23,40 @@
#include <linux/acpi.h>
#include "pci.h"
@@ -76949,9 +121637,66 @@ diff -rpuN linux-2.6.18.8/drivers/pci/quirks.c linux-2.6.18-xen-3.2.0/drivers/pc
/* The Mellanox Tavor device gives false positive parity errors
* Mark this device with a broken_parity_status, to allow
* PCI scanning code to "skip" this now blacklisted device.
-diff -rpuN linux-2.6.18.8/drivers/pnp/manager.c linux-2.6.18-xen-3.2.0/drivers/pnp/manager.c
---- linux-2.6.18.8/drivers/pnp/manager.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/pnp/manager.c 2008-02-15 16:22:01.000000000 -0800
+@@ -839,6 +873,25 @@ static void __init quirk_disable_pxb(str
+ }
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
+
++static void __devinit quirk_sb600_sata(struct pci_dev *pdev)
++{
++ /* set sb600/sb700/sb800 sata to ahci mode */
++ u8 tmp;
++
++ pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &tmp);
++ if (tmp == 0x01) {
++ pci_read_config_byte(pdev, 0x40, &tmp);
++ pci_write_config_byte(pdev, 0x40, tmp|1);
++ pci_write_config_byte(pdev, 0x9, 1);
++ pci_write_config_byte(pdev, 0xa, 6);
++ pci_write_config_byte(pdev, 0x40, tmp);
++
++ pdev->class = PCI_CLASS_STORAGE_SATA_AHCI;
++ dev_info(&pdev->dev, "set SATA to AHCI mode\n");
++ }
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_sb600_sata);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_sb600_sata);
+
+ /*
+ * Serverworks CSB5 IDE does not fully support native mode
+@@ -1494,10 +1547,11 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_N
+
+ static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
+ {
+- u16 command;
++ u16 command, pmcsr;
+ u32 bar;
+ u8 __iomem *csr;
+ u8 cmd_hi;
++ int pm;
+
+ switch (dev->device) {
+ /* PCI IDs taken from drivers/net/e100.c */
+@@ -1532,6 +1586,17 @@ static void __devinit quirk_e100_interru
+ if (!(command & PCI_COMMAND_MEMORY) || !bar)
+ return;
+
++ /*
++ * Check that the device is in the D0 power state. If it's not,
++ * there is no point to look any further.
++ */
++ pm = pci_find_capability(dev, PCI_CAP_ID_PM);
++ if (pm) {
++ pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
++ if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0)
++ return;
++ }
++
+ csr = ioremap(bar, 8);
+ if (!csr) {
+ printk(KERN_WARNING "PCI: Can't map %s e100 registers\n",
+diff -rpuN linux-2.6.18.8/drivers/pnp/manager.c linux-2.6.18-xen-3.3.0/drivers/pnp/manager.c
+--- linux-2.6.18.8/drivers/pnp/manager.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/pnp/manager.c 2008-08-21 11:36:07.000000000 +0200
@@ -168,7 +168,7 @@ static int pnp_assign_irq(struct pnp_dev
return 0;
}
@@ -77027,10 +121772,35 @@ diff -rpuN linux-2.6.18.8/drivers/pnp/manager.c linux-2.6.18-xen-3.2.0/drivers/p
ndma++;
dma = dma->next;
}
-diff -rpuN linux-2.6.18.8/drivers/scsi/ahci.c linux-2.6.18-xen-3.2.0/drivers/scsi/ahci.c
---- linux-2.6.18.8/drivers/scsi/ahci.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/scsi/ahci.c 2008-02-15 16:22:04.000000000 -0800
-@@ -317,6 +317,28 @@ static const struct pci_device_id ahci_p
+diff -rpuN linux-2.6.18.8/drivers/scsi/ahci.c linux-2.6.18-xen-3.3.0/drivers/scsi/ahci.c
+--- linux-2.6.18.8/drivers/scsi/ahci.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/scsi/ahci.c 2008-08-21 11:36:07.000000000 +0200
+@@ -78,6 +78,7 @@ enum {
+
+ board_ahci = 0,
+ board_ahci_vt8251 = 1,
++ board_ahci_sb700 = 2,
+
+ /* global controller registers */
+ HOST_CAP = 0x00, /* host capabilities */
+@@ -283,6 +284,16 @@ static const struct ata_port_info ahci_p
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &ahci_ops,
+ },
++ {
++ .sht = &ahci_sht,
++ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
++ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
++ ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
++ ATA_FLAG_IPM,
++ .pio_mask = 0x1f, /* pio0-4 */
++ .udma_mask = 0x7f,
++ .port_ops = &ahci_ops,
++ },
+ };
+
+ static const struct pci_device_id ahci_pci_tbl[] = {
+@@ -317,6 +328,36 @@ static const struct pci_device_id ahci_p
board_ahci }, /* ICH8M */
{ PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH8M */
@@ -77056,22 +121826,59 @@ diff -rpuN linux-2.6.18.8/drivers/scsi/ahci.c linux-2.6.18-xen-3.2.0/drivers/scs
+ board_ahci }, /* ICH9 */
+ { PCI_VENDOR_ID_INTEL, 0x294e, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH9M */
++ { PCI_VENDOR_ID_INTEL, 0x3a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci }, /* ICH10 */
++ { PCI_VENDOR_ID_INTEL, 0x3a05, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci }, /* ICH10 */
++ { PCI_VENDOR_ID_INTEL, 0x3a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci }, /* ICH10 */
++ { PCI_VENDOR_ID_INTEL, 0x3a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci }, /* ICH10 */
/* JMicron */
{ 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-diff -rpuN linux-2.6.18.8/drivers/scsi/ata_piix.c linux-2.6.18-xen-3.2.0/drivers/scsi/ata_piix.c
---- linux-2.6.18.8/drivers/scsi/ata_piix.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/scsi/ata_piix.c 2008-02-15 16:22:04.000000000 -0800
-@@ -125,6 +125,7 @@ enum {
+@@ -335,6 +376,18 @@ static const struct pci_device_id ahci_p
+ board_ahci }, /* ATI SB600 non-raid */
+ { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ATI SB600 raid */
++ { PCI_VENDOR_ID_ATI, 0x4390, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci_sb700 },
++ { PCI_VENDOR_ID_ATI, 0x4391, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci_sb700 },
++ { PCI_VENDOR_ID_ATI, 0x4392, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci_sb700 },
++ { PCI_VENDOR_ID_ATI, 0x4393, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci_sb700 },
++ { PCI_VENDOR_ID_ATI, 0x4394, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci_sb700 },
++ { PCI_VENDOR_ID_ATI, 0x4395, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ board_ahci_sb700 },
+
+ /* VIA */
+ { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+diff -rpuN linux-2.6.18.8/drivers/scsi/ata_piix.c linux-2.6.18-xen-3.3.0/drivers/scsi/ata_piix.c
+--- linux-2.6.18.8/drivers/scsi/ata_piix.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/scsi/ata_piix.c 2008-08-21 11:36:07.000000000 +0200
+@@ -125,6 +125,8 @@ enum {
ich6m_sata_ahci = 6,
ich7m_sata_ahci = 7,
ich8_sata_ahci = 8,
+ ich9_sata_ahci = 9,
++ ich8_2port_sata = 10,
/* constants for mapping table */
P0 = 0, /* port 0 */
-@@ -198,6 +199,18 @@ static const struct pci_device_id piix_p
- { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+@@ -192,12 +194,32 @@ static const struct pci_device_id piix_p
+ { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7m_sata_ahci },
+ /* Enterprise Southbridge 2 (where's the datasheet?) */
+ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+- /* SATA Controller 1 IDE (ICH8, no datasheet yet) */
++ /* SATA Controller 1 IDE (ICH8) */
+ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+- /* SATA Controller 2 IDE (ICH8, ditto) */
+- { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ /* SATA Controller 2 IDE (ICH8) */
++ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* Mobile SATA Controller IDE (ICH8M, ditto) */
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ /* SATA Controller 1 IDE (ICH9) */
@@ -77086,10 +121893,18 @@ diff -rpuN linux-2.6.18.8/drivers/scsi/ata_piix.c linux-2.6.18-xen-3.2.0/drivers
+ { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_sata_ahci },
+ /* Mobile SATA Controller 2 IDE (ICH9M) */
+ { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_sata_ahci },
++ /* SATA Controller IDE (ICH10) */
++ { 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ /* SATA Controller IDE (ICH10) */
++ { 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
++ /* SATA Controller IDE (ICH10) */
++ { 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ /* SATA Controller IDE (ICH10) */
++ { 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
{ } /* terminate list */
};
-@@ -361,9 +374,22 @@ static const struct piix_map_db ich8_map
+@@ -361,9 +383,34 @@ static const struct piix_map_db ich8_map
.present_shift = 8,
.map = {
/* PM PS SM SS MAP */
@@ -77111,18 +121926,31 @@ diff -rpuN linux-2.6.18.8/drivers/scsi/ata_piix.c linux-2.6.18-xen-3.2.0/drivers
+ { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */
+ { RV, RV, RV, RV },
+ { IDE, IDE, NA, NA }, /* 10b (IDE mode) */
++ { RV, RV, RV, RV },
++ },
++};
++
++static const struct piix_map_db ich8_2port_map_db = {
++ .mask = 0x3,
++ .port_enable = 0x3,
++ .map = {
++ /* PM PS SM SS MAP */
++ { P0, NA, P1, NA }, /* 00b */
++ { RV, RV, RV, RV }, /* 01b */
++ { RV, RV, RV, RV }, /* 10b */
{ RV, RV, RV, RV },
},
};
-@@ -376,6 +402,7 @@ static const struct piix_map_db *piix_ma
+@@ -376,6 +423,8 @@ static const struct piix_map_db *piix_ma
[ich6m_sata_ahci] = &ich6m_map_db,
[ich7m_sata_ahci] = &ich7m_map_db,
[ich8_sata_ahci] = &ich8_map_db,
+ [ich9_sata_ahci] = &ich9_map_db,
++ [ich8_2port_sata] = &ich8_2port_map_db,
};
static struct ata_port_info piix_port_info[] = {
-@@ -487,6 +514,18 @@ static struct ata_port_info piix_port_in
+@@ -487,6 +536,30 @@ static struct ata_port_info piix_port_in
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops,
},
@@ -77138,12 +121966,24 @@ diff -rpuN linux-2.6.18.8/drivers/scsi/ata_piix.c linux-2.6.18-xen-3.2.0/drivers
+ .udma_mask = 0x7f, /* udma0-6 */
+ .port_ops = &piix_sata_ops,
+ },
++
++ /* ich8_2port_sata: 11: */
++ {
++ .sht = &piix_sht,
++ .host_flags = ATA_FLAG_SATA |
++ PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
++ PIIX_FLAG_AHCI,
++ .pio_mask = 0x1f, /* pio0-4 */
++ .mwdma_mask = 0x07, /* mwdma0-2 */
++ .udma_mask = ATA_UDMA6,
++ .port_ops = &piix_pata_ops,
++ },
};
static struct pci_bits piix_enable_bits[] = {
-diff -rpuN linux-2.6.18.8/drivers/serial/Kconfig linux-2.6.18-xen-3.2.0/drivers/serial/Kconfig
---- linux-2.6.18.8/drivers/serial/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/serial/Kconfig 2008-02-15 16:22:05.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/serial/Kconfig linux-2.6.18-xen-3.3.0/drivers/serial/Kconfig
+--- linux-2.6.18.8/drivers/serial/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/serial/Kconfig 2008-08-21 11:36:07.000000000 +0200
@@ -11,6 +11,7 @@ menu "Serial drivers"
config SERIAL_8250
tristate "8250/16550 and compatible serial support"
@@ -77152,9 +121992,9 @@ diff -rpuN linux-2.6.18.8/drivers/serial/Kconfig linux-2.6.18-xen-3.2.0/drivers/
select SERIAL_CORE
---help---
This selects whether you want to include the driver for the standard
-diff -rpuN linux-2.6.18.8/drivers/video/console/Kconfig linux-2.6.18-xen-3.2.0/drivers/video/console/Kconfig
---- linux-2.6.18.8/drivers/video/console/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/video/console/Kconfig 2008-02-15 16:22:05.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/video/console/Kconfig linux-2.6.18-xen-3.3.0/drivers/video/console/Kconfig
+--- linux-2.6.18.8/drivers/video/console/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/video/console/Kconfig 2008-08-21 11:36:07.000000000 +0200
@@ -53,6 +53,7 @@ config VGACON_SOFT_SCROLLBACK_SIZE
config VIDEO_SELECT
bool "Video mode selection support"
@@ -77163,326 +122003,22 @@ diff -rpuN linux-2.6.18.8/drivers/video/console/Kconfig linux-2.6.18-xen-3.2.0/d
---help---
This enables support for text mode selection on kernel startup. If
you want to take advantage of some high-resolution text mode your
-diff -rpuN linux-2.6.18.8/drivers/xen/Kconfig linux-2.6.18-xen-3.2.0/drivers/xen/Kconfig
---- linux-2.6.18.8/drivers/xen/Kconfig 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/Kconfig 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,282 @@
-+#
-+# This Kconfig describe xen options
-+#
-+
-+mainmenu "Xen Configuration"
-+
-+config XEN
-+ bool
-+
-+if XEN
-+config XEN_INTERFACE_VERSION
-+ hex
-+ default 0x00030207
-+
-+menu "XEN"
-+
-+config XEN_PRIVILEGED_GUEST
-+ bool "Privileged Guest (domain 0)"
-+ help
-+ Support for privileged operation (domain 0)
-+
-+config XEN_UNPRIVILEGED_GUEST
-+ def_bool !XEN_PRIVILEGED_GUEST
-+
-+config XEN_PRIVCMD
-+ def_bool y
-+ depends on PROC_FS
-+
-+config XEN_XENBUS_DEV
-+ def_bool y
-+ depends on PROC_FS
-+
-+config XEN_BACKEND
-+ tristate "Backend driver support"
-+ default XEN_PRIVILEGED_GUEST
-+ help
-+ Support for backend device drivers that provide I/O services
-+ to other virtual machines.
-+
-+config XEN_BLKDEV_BACKEND
-+ tristate "Block-device backend driver"
-+ depends on XEN_BACKEND
-+ default XEN_BACKEND
-+ help
-+ The block-device backend driver allows the kernel to export its
-+ block devices to other guests via a high-performance shared-memory
-+ interface.
-+
-+config XEN_BLKDEV_TAP
-+ tristate "Block-device tap backend driver"
-+ depends on XEN_BACKEND
-+ default XEN_BACKEND
-+ help
-+ The block tap driver is an alternative to the block back driver
-+ and allows VM block requests to be redirected to userspace through
-+ a device interface. The tap allows user-space development of
-+ high-performance block backends, where disk images may be implemented
-+ as files, in memory, or on other hosts across the network. This
-+ driver can safely coexist with the existing blockback driver.
-+
-+config XEN_NETDEV_BACKEND
-+ tristate "Network-device backend driver"
-+ depends on XEN_BACKEND && NET
-+ default XEN_BACKEND
-+ help
-+ The network-device backend driver allows the kernel to export its
-+ network devices to other guests via a high-performance shared-memory
-+ interface.
-+
-+config XEN_NETDEV_PIPELINED_TRANSMITTER
-+ bool "Pipelined transmitter (DANGEROUS)"
-+ depends on XEN_NETDEV_BACKEND
-+ help
-+ If the net backend is a dumb domain, such as a transparent Ethernet
-+ bridge with no local IP interface, it is safe to say Y here to get
-+ slightly lower network overhead.
-+ If the backend has a local IP interface; or may be doing smart things
-+ like reassembling packets to perform firewall filtering; or if you
-+ are unsure; or if you experience network hangs when this option is
-+ enabled; then you must say N here.
-+
-+config XEN_NETDEV_LOOPBACK
-+ tristate "Network-device loopback driver"
-+ depends on XEN_NETDEV_BACKEND
-+ help
-+ A two-interface loopback device to emulate a local netfront-netback
-+ connection. If unsure, it is probably safe to say N here.
-+
-+config XEN_PCIDEV_BACKEND
-+ tristate "PCI-device backend driver"
-+ depends on PCI && XEN_BACKEND
-+ default XEN_BACKEND
-+ help
-+ The PCI device backend driver allows the kernel to export arbitrary
-+ PCI devices to other guests. If you select this to be a module, you
-+ will need to make sure no other driver has bound to the device(s)
-+ you want to make visible to other guests.
-+
-+choice
-+ prompt "PCI Backend Mode"
-+ depends on XEN_PCIDEV_BACKEND
-+ default XEN_PCIDEV_BACKEND_VPCI if !IA64
-+ default XEN_PCIDEV_BACKEND_CONTROLLER if IA64
-+
-+config XEN_PCIDEV_BACKEND_VPCI
-+ bool "Virtual PCI"
-+ ---help---
-+ This PCI Backend hides the true PCI topology and makes the frontend
-+ think there is a single PCI bus with only the exported devices on it.
-+ For example, a device at 03:05.0 will be re-assigned to 00:00.0. A
-+ second device at 02:1a.1 will be re-assigned to 00:01.1.
-+
-+config XEN_PCIDEV_BACKEND_PASS
-+ bool "Passthrough"
-+ ---help---
-+ This PCI Backend provides a real view of the PCI topology to the
-+ frontend (for example, a device at 06:01.b will still appear at
-+ 06:01.b to the frontend). This is similar to how Xen 2.0.x exposed
-+ PCI devices to its driver domains. This may be required for drivers
-+ which depend on finding their hardward in certain bus/slot
-+ locations.
-+
-+config XEN_PCIDEV_BACKEND_SLOT
-+ bool "Slot"
-+ ---help---
-+ This PCI Backend hides the true PCI topology and makes the frontend
-+ think there is a single PCI bus with only the exported devices on it.
-+ Contrary to the virtual PCI backend, a function becomes a new slot.
-+ For example, a device at 03:05.2 will be re-assigned to 00:00.0. A
-+ second device at 02:1a.1 will be re-assigned to 00:01.0.
-+
-+config XEN_PCIDEV_BACKEND_CONTROLLER
-+ bool "Controller"
-+ depends on IA64
-+ ---help---
-+ This PCI backend virtualizes the PCI bus topology by providing a
-+ virtual bus per PCI root device. Devices which are physically under
-+ the same root bus will appear on the same virtual bus. For systems
-+ with complex I/O addressing, this is the only backend which supports
-+ extended I/O port spaces and MMIO translation offsets. This backend
-+ also supports slot virtualization. For example, a device at
-+ 0000:01:02.1 will be re-assigned to 0000:00:00.0. A second device
-+ at 0000:02:05.0 (behind a P2P bridge on bus 0000:01) will be
-+ re-assigned to 0000:00:01.0. A third device at 0000:16:05.0 (under
-+ a different PCI root bus) will be re-assigned to 0000:01:00.0.
-+
-+endchoice
-+
-+config XEN_PCIDEV_BE_DEBUG
-+ bool "PCI Backend Debugging"
-+ depends on XEN_PCIDEV_BACKEND
-+
-+config XEN_TPMDEV_BACKEND
-+ tristate "TPM-device backend driver"
-+ depends on XEN_BACKEND
-+ help
-+ The TPM-device backend driver
-+
-+config XEN_BLKDEV_FRONTEND
-+ tristate "Block-device frontend driver"
-+ default y
-+ help
-+ The block-device frontend driver allows the kernel to access block
-+ devices mounted within another guest OS. Unless you are building a
-+ dedicated device-driver domain, or your master control domain
-+ (domain 0), then you almost certainly want to say Y here.
-+
-+config XEN_NETDEV_FRONTEND
-+ tristate "Network-device frontend driver"
-+ depends on NET
-+ default y
-+ help
-+ The network-device frontend driver allows the kernel to access
-+ network interfaces within another guest OS. Unless you are building a
-+ dedicated device-driver domain, or your master control domain
-+ (domain 0), then you almost certainly want to say Y here.
-+
-+config XEN_GRANT_DEV
-+ tristate "User-space granted page access driver"
-+ default XEN_PRIVILEGED_GUEST
-+ help
-+ Device for accessing (in user-space) pages that have been granted
-+ by other domains.
-+
-+config XEN_FRAMEBUFFER
-+ tristate "Framebuffer-device frontend driver"
-+ depends on FB
-+ select FB_CFB_FILLRECT
-+ select FB_CFB_COPYAREA
-+ select FB_CFB_IMAGEBLIT
-+ default y
-+ help
-+ The framebuffer-device frontend drivers allows the kernel to create a
-+ virtual framebuffer. This framebuffer can be viewed in another
-+ domain. Unless this domain has access to a real video card, you
-+ probably want to say Y here.
-+
-+config XEN_KEYBOARD
-+ tristate "Keyboard-device frontend driver"
-+ depends on XEN_FRAMEBUFFER && INPUT
-+ default y
-+ help
-+ The keyboard-device frontend driver allows the kernel to create a
-+ virtual keyboard. This keyboard can then be driven by another
-+ domain. If you've said Y to CONFIG_XEN_FRAMEBUFFER, you probably
-+ want to say Y here.
-+
-+config XEN_SCRUB_PAGES
-+ bool "Scrub memory before freeing it to Xen"
-+ default y
-+ help
-+ Erase memory contents before freeing it back to Xen's global
-+ pool. This ensures that any secrets contained within that
-+ memory (e.g., private keys) cannot be found by other guests that
-+ may be running on the machine. Most people will want to say Y here.
-+ If security is not a concern then you may increase performance by
-+ saying N.
-+
-+config XEN_DISABLE_SERIAL
-+ bool "Disable serial port drivers"
-+ default y
-+ help
-+ Disable serial port drivers, allowing the Xen console driver
-+ to provide a serial console at ttyS0.
-+
-+config XEN_SYSFS
-+ tristate "Export Xen attributes in sysfs"
-+ depends on SYSFS
-+ select SYS_HYPERVISOR
-+ default y
-+ help
-+ Xen hypervisor attributes will show up under /sys/hypervisor/.
-+
-+choice
-+ prompt "Xen version compatibility"
-+ default XEN_COMPAT_030002_AND_LATER
-+
-+ config XEN_COMPAT_030002_AND_LATER
-+ bool "3.0.2 and later"
-+
-+ config XEN_COMPAT_030004_AND_LATER
-+ bool "3.0.4 and later"
-+
-+ config XEN_COMPAT_030100_AND_LATER
-+ bool "3.1.0 and later"
-+
-+ config XEN_COMPAT_LATEST_ONLY
-+ bool "no compatibility code"
-+
-+endchoice
-+
-+config XEN_COMPAT
-+ hex
-+ default 0xffffff if XEN_COMPAT_LATEST_ONLY
-+ default 0x030100 if XEN_COMPAT_030100_AND_LATER
-+ default 0x030004 if XEN_COMPAT_030004_AND_LATER
-+ default 0x030002 if XEN_COMPAT_030002_AND_LATER
-+ default 0
-+
-+endmenu
-+
-+config HAVE_IRQ_IGNORE_UNHANDLED
-+ def_bool y
-+
-+config NO_IDLE_HZ
-+ def_bool y
-+
-+config XEN_SMPBOOT
-+ def_bool y
-+ depends on SMP && !PPC_XEN
-+
-+config XEN_BALLOON
-+ def_bool y
-+ depends on !PPC_XEN
-+
-+config XEN_XENCOMM
-+ bool
-+
-+config XEN_DEVMEM
-+ def_bool y
-+
-+endif
-diff -rpuN linux-2.6.18.8/drivers/xen/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/Makefile
---- linux-2.6.18.8/drivers/xen/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,20 @@
-+obj-y += core/
-+obj-y += console/
-+obj-y += evtchn/
-+obj-y += xenbus/
-+obj-y += char/
-+
-+obj-y += util.o
-+obj-$(CONFIG_XEN_BALLOON) += balloon/
-+obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
-+obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/
-+obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
-+obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/
-+obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/
-+obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/
-+obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback/
-+obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront/
-+obj-$(CONFIG_XEN_FRAMEBUFFER) += fbfront/
-+obj-$(CONFIG_XEN_KEYBOARD) += fbfront/
-+obj-$(CONFIG_XEN_PRIVCMD) += privcmd/
-+obj-$(CONFIG_XEN_GRANT_DEV) += gntdev/
-diff -rpuN linux-2.6.18.8/drivers/xen/balloon/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/balloon/Makefile
---- linux-2.6.18.8/drivers/xen/balloon/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/balloon/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,2 @@
-+
-+obj-y := balloon.o sysfs.o
-diff -rpuN linux-2.6.18.8/drivers/xen/balloon/balloon.c linux-2.6.18-xen-3.2.0/drivers/xen/balloon/balloon.c
---- linux-2.6.18.8/drivers/xen/balloon/balloon.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/balloon/balloon.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,687 @@
+diff -rpuN linux-2.6.18.8/drivers/video/Kconfig linux-2.6.18-xen-3.3.0/drivers/video/Kconfig
+--- linux-2.6.18.8/drivers/video/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/video/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -1254,7 +1254,7 @@ config FB_CYBLA
+ tristate "Cyberblade/i1 support"
+ depends on FB && PCI && X86_32 && !64BIT
+ select FB_CFB_IMAGEBLIT
+- select VIDEO_SELECT
++ select VIDEO_SELECT if !XEN
+ ---help---
+ This driver is supposed to support the Trident Cyberblade/i1
+ graphics core integrated in the VIA VT8601A North Bridge,
+diff -rpuN linux-2.6.18.8/drivers/xen/balloon/balloon.c linux-2.6.18-xen-3.3.0/drivers/xen/balloon/balloon.c
+--- linux-2.6.18.8/drivers/xen/balloon/balloon.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/balloon/balloon.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,724 @@
+/******************************************************************************
+ * balloon.c
+ *
@@ -77679,6 +122215,43 @@ diff -rpuN linux-2.6.18.8/drivers/xen/balloon/balloon.c linux-2.6.18-xen-3.2.0/d
+ return target;
+}
+
++static unsigned long minimum_target(void)
++{
++#ifndef CONFIG_XEN
++#define max_pfn num_physpages
++#endif
++ unsigned long min_pages, curr_pages = current_target();
++
++#define MB2PAGES(mb) ((mb) << (20 - PAGE_SHIFT))
++ /* Simple continuous piecewiese linear function:
++ * max MiB -> min MiB gradient
++ * 0 0
++ * 16 16
++ * 32 24
++ * 128 72 (1/2)
++ * 512 168 (1/4)
++ * 2048 360 (1/8)
++ * 8192 552 (1/32)
++ * 32768 1320
++ * 131072 4392
++ */
++ if (max_pfn < MB2PAGES(128))
++ min_pages = MB2PAGES(8) + (max_pfn >> 1);
++ else if (max_pfn < MB2PAGES(512))
++ min_pages = MB2PAGES(40) + (max_pfn >> 2);
++ else if (max_pfn < MB2PAGES(2048))
++ min_pages = MB2PAGES(104) + (max_pfn >> 3);
++ else
++ min_pages = MB2PAGES(296) + (max_pfn >> 5);
++#undef MB2PAGES
++
++ /* Don't enforce growth */
++ return min(min_pages, curr_pages);
++#ifndef CONFIG_XEN
++#undef max_pfn
++#endif
++}
++
+static int increase_reservation(unsigned long nr_pages)
+{
+ unsigned long pfn, i, flags;
@@ -77869,7 +122442,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/balloon/balloon.c linux-2.6.18-xen-3.2.0/d
+{
+ /* No need for lock. Not read-modify-write updates. */
+ bs.hard_limit = ~0UL;
-+ bs.target_pages = target;
++ bs.target_pages = max(target, minimum_target());
+ schedule_work(&balloon_worker);
+}
+
@@ -78170,9 +122743,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/balloon/balloon.c linux-2.6.18-xen-3.2.0/d
+EXPORT_SYMBOL_GPL(balloon_release_driver_page);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/balloon/common.h linux-2.6.18-xen-3.2.0/drivers/xen/balloon/common.h
---- linux-2.6.18.8/drivers/xen/balloon/common.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/balloon/common.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/balloon/common.h linux-2.6.18-xen-3.3.0/drivers/xen/balloon/common.h
+--- linux-2.6.18.8/drivers/xen/balloon/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/balloon/common.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,58 @@
+/******************************************************************************
+ * balloon/common.h
@@ -78232,9 +122805,15 @@ diff -rpuN linux-2.6.18.8/drivers/xen/balloon/common.h linux-2.6.18-xen-3.2.0/dr
+void balloon_set_new_target(unsigned long target);
+
+#endif /* __XEN_BALLOON_COMMON_H__ */
-diff -rpuN linux-2.6.18.8/drivers/xen/balloon/sysfs.c linux-2.6.18-xen-3.2.0/drivers/xen/balloon/sysfs.c
---- linux-2.6.18.8/drivers/xen/balloon/sysfs.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/balloon/sysfs.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/balloon/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/balloon/Makefile
+--- linux-2.6.18.8/drivers/xen/balloon/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/balloon/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2 @@
++
++obj-y := balloon.o sysfs.o
+diff -rpuN linux-2.6.18.8/drivers/xen/balloon/sysfs.c linux-2.6.18-xen-3.3.0/drivers/xen/balloon/sysfs.c
+--- linux-2.6.18.8/drivers/xen/balloon/sysfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/balloon/sysfs.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,170 @@
+/******************************************************************************
+ * balloon/sysfs.c
@@ -78277,7 +122856,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/balloon/sysfs.c linux-2.6.18-xen-3.2.0/dri
+#include <xen/platform-compat.h>
+#endif
+
-+#define BALLOON_CLASS_NAME "memory"
++#define BALLOON_CLASS_NAME "xen_memory"
+
+#define BALLOON_SHOW(name, format, args...) \
+ static ssize_t show_##name(struct sys_device *dev, \
@@ -78406,17 +122985,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/balloon/sysfs.c linux-2.6.18-xen-3.2.0/dri
+{
+ unregister_balloon(&balloon_sysdev);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/blkback/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/blkback/Makefile
---- linux-2.6.18.8/drivers/xen/blkback/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkback/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,3 @@
-+obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o
-+
-+blkbk-y := blkback.o xenbus.o interface.o vbd.o
-diff -rpuN linux-2.6.18.8/drivers/xen/blkback/blkback.c linux-2.6.18-xen-3.2.0/drivers/xen/blkback/blkback.c
---- linux-2.6.18.8/drivers/xen/blkback/blkback.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkback/blkback.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,643 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/blkback/blkback.c linux-2.6.18-xen-3.3.0/drivers/xen/blkback/blkback.c
+--- linux-2.6.18.8/drivers/xen/blkback/blkback.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkback/blkback.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,646 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/main.c
+ *
@@ -78592,8 +123164,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/blkback.c linux-2.6.18-xen-3.2.0/d
+ handle = pending_handle(req, i);
+ if (handle == BLKBACK_INVALID_HANDLE)
+ continue;
-+ gnttab_set_unmap_op(&unmap[i], vaddr(req, i), GNTMAP_host_map,
-+ handle);
++ gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i),
++ GNTMAP_host_map, handle);
+ pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
+ invcount++;
+ }
@@ -78763,6 +123335,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/blkback.c linux-2.6.18-xen-3.2.0/d
+ }
+ blk_rings->common.req_cons = ++rc; /* before make_response() */
+
++ /* Apply all sanity checks to /private copy/ of request. */
++ barrier();
++
+ switch (req.operation) {
+ case BLKIF_OP_READ:
+ blkif->st_rd_req++;
@@ -79060,9 +123635,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/blkback.c linux-2.6.18-xen-3.2.0/d
+module_init(blkif_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/blkback/common.h linux-2.6.18-xen-3.2.0/drivers/xen/blkback/common.h
---- linux-2.6.18.8/drivers/xen/blkback/common.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkback/common.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/blkback/common.h linux-2.6.18-xen-3.3.0/drivers/xen/blkback/common.h
+--- linux-2.6.18.8/drivers/xen/blkback/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkback/common.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,139 @@
+/*
+ * This program is free software; you can redistribute it and/or
@@ -79176,7 +123751,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/common.h linux-2.6.18-xen-3.2.0/dr
+
+/* Create a vbd. */
+int vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, unsigned major,
-+ unsigned minor, int readonly);
++ unsigned minor, int readonly, int cdrom);
+void vbd_free(struct vbd *vbd);
+
+unsigned long long vbd_size(struct vbd *vbd);
@@ -79203,9 +123778,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/common.h linux-2.6.18-xen-3.2.0/dr
+ struct backend_info *be, int state);
+
+#endif /* __BLKIF__BACKEND__COMMON_H__ */
-diff -rpuN linux-2.6.18.8/drivers/xen/blkback/interface.c linux-2.6.18-xen-3.2.0/drivers/xen/blkback/interface.c
---- linux-2.6.18.8/drivers/xen/blkback/interface.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkback/interface.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/blkback/interface.c linux-2.6.18-xen-3.3.0/drivers/xen/blkback/interface.c
+--- linux-2.6.18.8/drivers/xen/blkback/interface.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkback/interface.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,181 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/interface.c
@@ -79388,9 +123963,16 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/interface.c linux-2.6.18-xen-3.2.0
+ blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
+ 0, 0, NULL, NULL);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/blkback/vbd.c linux-2.6.18-xen-3.2.0/drivers/xen/blkback/vbd.c
---- linux-2.6.18.8/drivers/xen/blkback/vbd.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkback/vbd.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/blkback/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/blkback/Makefile
+--- linux-2.6.18.8/drivers/xen/blkback/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkback/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o
++
++blkbk-y := blkback.o xenbus.o interface.o vbd.o
+diff -rpuN linux-2.6.18.8/drivers/xen/blkback/vbd.c linux-2.6.18-xen-3.3.0/drivers/xen/blkback/vbd.c
+--- linux-2.6.18.8/drivers/xen/blkback/vbd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkback/vbd.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,118 @@
+/******************************************************************************
+ * blkback/vbd.c
@@ -79445,7 +124027,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/vbd.c linux-2.6.18-xen-3.2.0/drive
+}
+
+int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
-+ unsigned minor, int readonly)
++ unsigned minor, int readonly, int cdrom)
+{
+ struct vbd *vbd;
+ struct block_device *bdev;
@@ -79475,7 +124057,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/vbd.c linux-2.6.18-xen-3.2.0/drive
+ return -ENOENT;
+ }
+
-+ if (vbd->bdev->bd_disk->flags & GENHD_FL_CD)
++ if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom)
+ vbd->type |= VDISK_CDROM;
+ if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
+ vbd->type |= VDISK_REMOVABLE;
@@ -79510,10 +124092,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/vbd.c linux-2.6.18-xen-3.2.0/drive
+ out:
+ return rc;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/blkback/xenbus.c linux-2.6.18-xen-3.2.0/drivers/xen/blkback/xenbus.c
---- linux-2.6.18.8/drivers/xen/blkback/xenbus.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkback/xenbus.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,533 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/blkback/xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/blkback/xenbus.c
+--- linux-2.6.18.8/drivers/xen/blkback/xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkback/xenbus.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,541 @@
+/* Xenbus code for blkif backend
+ Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+ Copyright (C) 2005 XenSource Ltd
@@ -79786,6 +124368,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ struct backend_info *be
+ = container_of(watch, struct backend_info, backend_watch);
+ struct xenbus_device *dev = be->dev;
++ int cdrom = 0;
++ char *device_type;
+
+ DPRINTK("");
+
@@ -79819,6 +124403,12 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ return;
+ }
+
++ device_type = xenbus_read(XBT_NIL, dev->otherend, "device-type", NULL);
++ if (!IS_ERR(device_type)) {
++ cdrom = strcmp(device_type, "cdrom") == 0;
++ kfree(device_type);
++ }
++
+ if (be->major == 0 && be->minor == 0) {
+ /* Front end dir is a number, which is used as the handle. */
+
@@ -79829,7 +124419,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ be->minor = minor;
+
+ err = vbd_create(be->blkif, handle, major, minor,
-+ (NULL == strchr(be->mode, 'w')));
++ (NULL == strchr(be->mode, 'w')), cdrom);
+ if (err) {
+ be->major = be->minor = 0;
+ xenbus_dev_fatal(dev, err, "creating vbd structure");
@@ -80027,7 +124617,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+/* ** Driver Registration ** */
+
+
-+static struct xenbus_device_id blkback_ids[] = {
++static const struct xenbus_device_id blkback_ids[] = {
+ { "vbd" },
+ { "" }
+};
@@ -80047,19 +124637,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+{
+ xenbus_register_backend(&blkback);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/blkfront/Makefile
---- linux-2.6.18.8/drivers/xen/blkfront/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkfront/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,5 @@
-+
-+obj-$(CONFIG_XEN_BLKDEV_FRONTEND) := xenblk.o
-+
-+xenblk-objs := blkfront.o vbd.o
-+
-diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0/drivers/xen/blkfront/blkfront.c
---- linux-2.6.18.8/drivers/xen/blkfront/blkfront.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkfront/blkfront.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,920 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.3.0/drivers/xen/blkfront/blkfront.c
+--- linux-2.6.18.8/drivers/xen/blkfront/blkfront.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkfront/blkfront.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,936 @@
+/******************************************************************************
+ * blkfront.c
+ *
@@ -80154,8 +124735,13 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0
+ err = xenbus_scanf(XBT_NIL, dev->nodename,
+ "virtual-device", "%i", &vdevice);
+ if (err != 1) {
-+ xenbus_dev_fatal(dev, err, "reading virtual-device");
-+ return err;
++ /* go looking in the extended area instead */
++ err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device-ext",
++ "%i", &vdevice);
++ if (err != 1) {
++ xenbus_dev_fatal(dev, err, "reading virtual-device");
++ return err;
++ }
+ }
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -80281,7 +124867,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0
+
+ info->ring_ref = GRANT_INVALID_REF;
+
-+ sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL|__GFP_HIGH);
++ sring = (blkif_sring_t *)__get_free_page(GFP_NOIO | __GFP_HIGH);
+ if (!sring) {
+ xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
+ return -ENOMEM;
@@ -80328,6 +124914,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0
+ case XenbusStateInitialising:
+ case XenbusStateInitWait:
+ case XenbusStateInitialised:
++ case XenbusStateReconfiguring:
++ case XenbusStateReconfigured:
+ case XenbusStateUnknown:
+ case XenbusStateClosed:
+ break;
@@ -80407,6 +124995,13 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0
+ return;
+ }
+
++ err = xlvbd_sysfs_addif(info);
++ if (err) {
++ xenbus_dev_fatal(info->xbdev, err, "xlvbd_sysfs_addif at %s",
++ info->xbdev->otherend);
++ return;
++ }
++
+ (void)xenbus_switch_state(info->xbdev, XenbusStateConnected);
+
+ /* Kick pending requests. */
@@ -80446,6 +125041,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0
+ /* Flush gnttab callback work. Must be done with no locks held. */
+ flush_scheduled_work();
+
++ xlvbd_sysfs_delif(info);
++
+ xlvbd_del(info);
+
+ out:
@@ -80877,7 +125474,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0
+ int j;
+
+ /* Stage 1: Make a safe copy of the shadow state. */
-+ copy = kmalloc(sizeof(info->shadow), GFP_KERNEL | __GFP_NOFAIL);
++ copy = kmalloc(sizeof(info->shadow), GFP_NOIO | __GFP_NOFAIL | __GFP_HIGH);
+ memcpy(copy, info->shadow, sizeof(info->shadow));
+
+ /* Stage 2: Set up free list. */
@@ -80945,7 +125542,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0
+/* ** Driver Registration ** */
+
+
-+static struct xenbus_device_id blkfront_ids[] = {
++static const struct xenbus_device_id blkfront_ids[] = {
+ { "vbd" },
+ { "" }
+};
@@ -80980,10 +125577,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/blkfront.c linux-2.6.18-xen-3.2.0
+module_exit(xlblk_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/block.h linux-2.6.18-xen-3.2.0/drivers/xen/blkfront/block.h
---- linux-2.6.18.8/drivers/xen/blkfront/block.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkfront/block.h 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,143 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/block.h linux-2.6.18-xen-3.3.0/drivers/xen/blkfront/block.h
+--- linux-2.6.18.8/drivers/xen/blkfront/block.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkfront/block.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,158 @@
+/******************************************************************************
+ * block.h
+ *
@@ -81126,11 +125723,35 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/block.h linux-2.6.18-xen-3.2.0/dr
+void xlvbd_del(struct blkfront_info *info);
+int xlvbd_barrier(struct blkfront_info *info);
+
++#ifdef CONFIG_SYSFS
++int xlvbd_sysfs_addif(struct blkfront_info *info);
++void xlvbd_sysfs_delif(struct blkfront_info *info);
++#else
++static inline int xlvbd_sysfs_addif(struct blkfront_info *info)
++{
++ return 0;
++}
++
++static inline void xlvbd_sysfs_delif(struct blkfront_info *info)
++{
++ ;
++}
++#endif
++
+#endif /* __XEN_DRIVERS_BLOCK_H__ */
-diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/drivers/xen/blkfront/vbd.c
---- linux-2.6.18.8/drivers/xen/blkfront/vbd.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blkfront/vbd.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,375 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/blkfront/Makefile
+--- linux-2.6.18.8/drivers/xen/blkfront/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkfront/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,5 @@
++
++obj-$(CONFIG_XEN_BLKDEV_FRONTEND) := xenblk.o
++
++xenblk-objs := blkfront.o vbd.o
++
+diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.3.0/drivers/xen/blkfront/vbd.c
+--- linux-2.6.18.8/drivers/xen/blkfront/vbd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blkfront/vbd.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,460 @@
+/******************************************************************************
+ * vbd.c
+ *
@@ -81176,6 +125797,11 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+#define BLKIF_MAJOR(dev) ((dev)>>8)
+#define BLKIF_MINOR(dev) ((dev) & 0xff)
+
++#define EXT_SHIFT 28
++#define EXTENDED (1<<EXT_SHIFT)
++#define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))
++#define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
++
+/*
+ * For convenience we distinguish between ide, scsi and 'other' (i.e.,
+ * potentially combinations of the two) in the naming scheme and in a few other
@@ -81184,7 +125810,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+
+#define NUM_IDE_MAJORS 10
+#define NUM_SCSI_MAJORS 17
-+#define NUM_VBD_MAJORS 1
++#define NUM_VBD_MAJORS 2
+
+static struct xlbd_type_info xlbd_ide_type = {
+ .partn_shift = 6,
@@ -81207,6 +125833,13 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+ .diskname = "xvd",
+};
+
++static struct xlbd_type_info xlbd_vbd_type_ext = {
++ .partn_shift = 8,
++ .disks_per_major = 256,
++ .devname = "xvd",
++ .diskname = "xvd",
++};
++
+static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
+ NUM_VBD_MAJORS];
+
@@ -81218,10 +125851,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+#define XLBD_MAJOR_SCSI_RANGE XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1
+#define XLBD_MAJOR_VBD_RANGE XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1
+
-+/* Information about our VBDs. */
-+#define MAX_VBDS 64
-+static LIST_HEAD(vbds_list);
-+
+static struct block_device_operations xlvbd_block_fops =
+{
+ .owner = THIS_MODULE,
@@ -81239,12 +125868,14 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+xlbd_alloc_major_info(int major, int minor, int index)
+{
+ struct xlbd_major_info *ptr;
++ int do_register;
+
+ ptr = kzalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
+ if (ptr == NULL)
+ return NULL;
+
+ ptr->major = major;
++ do_register = 1;
+
+ switch (index) {
+ case XLBD_MAJOR_IDE_RANGE:
@@ -81256,29 +125887,39 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+ ptr->index = index - XLBD_MAJOR_SCSI_START;
+ break;
+ case XLBD_MAJOR_VBD_RANGE:
-+ ptr->type = &xlbd_vbd_type;
-+ ptr->index = index - XLBD_MAJOR_VBD_START;
++ ptr->index = 0;
++ if ((index - XLBD_MAJOR_VBD_START) == 0)
++ ptr->type = &xlbd_vbd_type;
++ else
++ ptr->type = &xlbd_vbd_type_ext;
++
++ /*
++ * if someone already registered block major 202,
++ * don't try to register it again
++ */
++ if (major_info[XLBD_MAJOR_VBD_START] != NULL)
++ do_register = 0;
+ break;
+ }
+
-+ if (register_blkdev(ptr->major, ptr->type->devname)) {
-+ kfree(ptr);
-+ return NULL;
++ if (do_register) {
++ if (register_blkdev(ptr->major, ptr->type->devname)) {
++ kfree(ptr);
++ return NULL;
++ }
++
++ printk("xen-vbd: registered block device major %i\n", ptr->major);
+ }
+
-+ printk("xen-vbd: registered block device major %i\n", ptr->major);
+ major_info[index] = ptr;
+ return ptr;
+}
+
+static struct xlbd_major_info *
-+xlbd_get_major_info(int vdevice)
++xlbd_get_major_info(int major, int minor, int vdevice)
+{
+ struct xlbd_major_info *mi;
-+ int major, minor, index;
-+
-+ major = BLKIF_MAJOR(vdevice);
-+ minor = BLKIF_MINOR(vdevice);
++ int index;
+
+ switch (major) {
+ case IDE0_MAJOR: index = 0; break;
@@ -81299,7 +125940,12 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+ index = 18 + major - SCSI_DISK8_MAJOR;
+ break;
+ case SCSI_CDROM_MAJOR: index = 26; break;
-+ default: index = 27; break;
++ default:
++ if (!VDEV_IS_EXTENDED(vdevice))
++ index = 27;
++ else
++ index = 28;
++ break;
+ }
+
+ mi = ((major_info[index] != NULL) ? major_info[index] :
@@ -81355,7 +126001,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+}
+
+static int
-+xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity, int vdevice,
++xlvbd_alloc_gendisk(int major, int minor, blkif_sector_t capacity, int vdevice,
+ u16 vdisk_info, u16 sector_size,
+ struct blkfront_info *info)
+{
@@ -81369,7 +126015,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+ BUG_ON(info->mi != NULL);
+ BUG_ON(info->rq != NULL);
+
-+ mi = xlbd_get_major_info(vdevice);
++ mi = xlbd_get_major_info(major, minor, vdevice);
+ if (mi == NULL)
+ goto out;
+ info->mi = mi;
@@ -81451,15 +126097,30 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+{
+ struct block_device *bd;
+ int err = 0;
++ int major, minor;
++
++ if ((vdevice>>EXT_SHIFT) > 1) {
++ /* this is above the extended range; something is wrong */
++ printk(KERN_WARNING "blkfront: vdevice 0x%x is above the extended range; ignoring\n", vdevice);
++ return -ENODEV;
++ }
+
-+ info->dev = MKDEV(BLKIF_MAJOR(vdevice), BLKIF_MINOR(vdevice));
++ if (!VDEV_IS_EXTENDED(vdevice)) {
++ major = BLKIF_MAJOR(vdevice);
++ minor = BLKIF_MINOR(vdevice);
++ }
++ else {
++ major = 202;
++ minor = BLKIF_MINOR_EXT(vdevice);
++ }
+
++ info->dev = MKDEV(major, minor);
+ bd = bdget(info->dev);
+ if (bd == NULL)
+ return -ENODEV;
+
-+ err = xlvbd_alloc_gendisk(BLKIF_MINOR(vdevice), capacity, vdevice,
-+ vdisk_info, sector_size, info);
++ err = xlvbd_alloc_gendisk(major, minor, capacity, vdevice, vdisk_info,
++ sector_size, info);
+
+ bdput(bd);
+ return err;
@@ -81506,19 +126167,55 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blkfront/vbd.c linux-2.6.18-xen-3.2.0/driv
+ return -ENOSYS;
+}
+#endif
-diff -rpuN linux-2.6.18.8/drivers/xen/blktap/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/blktap/Makefile
---- linux-2.6.18.8/drivers/xen/blktap/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blktap/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,5 @@
-+LINUXINCLUDE += -I../xen/include/public/io
+
-+obj-$(CONFIG_XEN_BLKDEV_TAP) := xenblktap.o
++#ifdef CONFIG_SYSFS
++static ssize_t show_media(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct xenbus_device *xendev = to_xenbus_device(dev);
++ struct blkfront_info *info = xendev->dev.driver_data;
+
-+xenblktap-y := xenbus.o interface.o blktap.o
-diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/drivers/xen/blktap/blktap.c
---- linux-2.6.18.8/drivers/xen/blktap/blktap.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blktap/blktap.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,1645 @@
++ if (info->gd->flags & GENHD_FL_CD)
++ return sprintf(buf, "cdrom\n");
++ return sprintf(buf, "disk\n");
++}
++
++static struct device_attribute xlvbd_attrs[] = {
++ __ATTR(media, S_IRUGO, show_media, NULL),
++};
++
++int xlvbd_sysfs_addif(struct blkfront_info *info)
++{
++ int i;
++ int error = 0;
++
++ for (i = 0; i < ARRAY_SIZE(xlvbd_attrs); i++) {
++ error = device_create_file(info->gd->driverfs_dev,
++ &xlvbd_attrs[i]);
++ if (error)
++ goto fail;
++ }
++ return 0;
++
++fail:
++ while (--i >= 0)
++ device_remove_file(info->gd->driverfs_dev, &xlvbd_attrs[i]);
++ return error;
++}
++
++void xlvbd_sysfs_delif(struct blkfront_info *info)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(xlvbd_attrs); i++)
++ device_remove_file(info->gd->driverfs_dev, &xlvbd_attrs[i]);
++}
++
++#endif /* CONFIG_SYSFS */
+diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.3.0/drivers/xen/blktap/blktap.c
+--- linux-2.6.18.8/drivers/xen/blktap/blktap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blktap/blktap.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1681 @@
+/******************************************************************************
+ * drivers/xen/blktap/blktap.c
+ *
@@ -81613,6 +126310,11 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/dri
+ unsigned short busid;
+} domid_translate_t ;
+
++typedef struct domid_translate_ext {
++ unsigned short domid;
++ u32 busid;
++} domid_translate_ext_t ;
++
+/*Data struct associated with each of the tapdisk devices*/
+typedef struct tap_blkif {
+ struct vm_area_struct *vma; /*Shared memory area */
@@ -81631,7 +126333,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/dri
+ unsigned long *idx_map; /*Record the user ring id to kern
+ [req id, idx] tuple */
+ blkif_t *blkif; /*Associate blkif with tapdev */
-+ struct domid_translate trans; /*Translation from domid to bus. */
++ struct domid_translate_ext trans; /*Translation from domid to bus. */
+} tap_blkif_t;
+
+static struct tap_blkif *tapfds[MAX_TAP_DEV];
@@ -81734,6 +126436,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/dri
+#define BLKTAP_IOCTL_MAJOR 7
+#define BLKTAP_QUERY_ALLOC_REQS 8
+#define BLKTAP_IOCTL_FREEINTF 9
++#define BLKTAP_IOCTL_NEWINTF_EXT 50
+#define BLKTAP_IOCTL_PRINT_IDXS 100
+
+/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE) */
@@ -82029,6 +126732,13 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/dri
+ tap_blkif_t *info;
+ struct task_struct *ptask;
+
++ /*
++ * if the userland tools set things up wrong, this could be negative;
++ * just don't try to signal in this case
++ */
++ if (idx < 0)
++ return;
++
+ info = tapfds[idx];
+ if ((idx < 0) || (idx > MAX_TAP_DEV) || !info)
+ return;
@@ -82205,7 +126915,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/dri
+
+ /* Mark this VM as containing foreign pages, and set up mappings. */
+ map = kzalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
-+ * sizeof(struct page_struct*),
++ * sizeof(struct page *),
+ GFP_KERNEL);
+ if (map == NULL) {
+ WPRINTK("Couldn't alloc VM_FOREIGN map.\n");
@@ -82298,6 +127008,26 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/dri
+ info->trans.busid = tr->busid;
+ return info->minor;
+ }
++ case BLKTAP_IOCTL_NEWINTF_EXT:
++ {
++ void __user *udata = (void __user *) arg;
++ domid_translate_ext_t tr;
++
++ if (copy_from_user(&tr, udata, sizeof(domid_translate_ext_t)))
++ return -EFAULT;
++
++ DPRINTK("NEWINTF_EXT Req for domid %d and bus id %d\n",
++ tr.domid, tr.busid);
++ info = get_next_free_dev();
++ if (!info) {
++ WPRINTK("Error initialising /dev/xen/blktap - "
++ "No more devices\n");
++ return -1;
++ }
++ info->trans.domid = tr.domid;
++ info->trans.busid = tr.busid;
++ return info->minor;
++ }
+ case BLKTAP_IOCTL_FREEINTF:
+ {
+ unsigned long dev = arg;
@@ -82785,6 +127515,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/dri
+ }
+ blk_rings->common.req_cons = ++rc; /* before make_response() */
+
++ /* Apply all sanity checks to /private copy/ of request. */
++ barrier();
++
+ switch (req.operation) {
+ case BLKIF_OP_READ:
+ blkif->st_rd_req++;
@@ -83164,9 +127897,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/blktap.c linux-2.6.18-xen-3.2.0/dri
+module_init(blkif_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/blktap/common.h linux-2.6.18-xen-3.2.0/drivers/xen/blktap/common.h
---- linux-2.6.18.8/drivers/xen/blktap/common.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blktap/common.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/blktap/common.h linux-2.6.18-xen-3.3.0/drivers/xen/blktap/common.h
+--- linux-2.6.18.8/drivers/xen/blktap/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blktap/common.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,121 @@
+/*
+ * This program is free software; you can redistribute it and/or
@@ -83289,9 +128022,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/common.h linux-2.6.18-xen-3.2.0/dri
+void signal_tapdisk(int idx);
+
+#endif /* __BLKIF__BACKEND__COMMON_H__ */
-diff -rpuN linux-2.6.18.8/drivers/xen/blktap/interface.c linux-2.6.18-xen-3.2.0/drivers/xen/blktap/interface.c
---- linux-2.6.18.8/drivers/xen/blktap/interface.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blktap/interface.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/blktap/interface.c linux-2.6.18-xen-3.3.0/drivers/xen/blktap/interface.c
+--- linux-2.6.18.8/drivers/xen/blktap/interface.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blktap/interface.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,174 @@
+/******************************************************************************
+ * drivers/xen/blktap/interface.c
@@ -83467,9 +128200,18 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/interface.c linux-2.6.18-xen-3.2.0/
+ blkif_cachep = kmem_cache_create("blktapif_cache", sizeof(blkif_t),
+ 0, 0, NULL, NULL);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/blktap/xenbus.c linux-2.6.18-xen-3.2.0/drivers/xen/blktap/xenbus.c
---- linux-2.6.18.8/drivers/xen/blktap/xenbus.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/blktap/xenbus.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/blktap/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/blktap/Makefile
+--- linux-2.6.18.8/drivers/xen/blktap/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blktap/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,5 @@
++LINUXINCLUDE += -I../xen/include/public/io
++
++obj-$(CONFIG_XEN_BLKDEV_TAP) := xenblktap.o
++
++xenblktap-y := xenbus.o interface.o blktap.o
+diff -rpuN linux-2.6.18.8/drivers/xen/blktap/xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/blktap/xenbus.c
+--- linux-2.6.18.8/drivers/xen/blktap/xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/blktap/xenbus.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,477 @@
+/* drivers/xen/blktap/xenbus.c
+ *
@@ -83928,7 +128670,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/xenbus.c linux-2.6.18-xen-3.2.0/dri
+/* ** Driver Registration ** */
+
+
-+static struct xenbus_device_id blktap_ids[] = {
++static const struct xenbus_device_id blktap_ids[] = {
+ { "tap" },
+ { "" }
+};
@@ -83948,14 +128690,14 @@ diff -rpuN linux-2.6.18.8/drivers/xen/blktap/xenbus.c linux-2.6.18-xen-3.2.0/dri
+{
+ xenbus_register_backend(&blktap);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/char/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/char/Makefile
---- linux-2.6.18.8/drivers/xen/char/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/char/Makefile 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/char/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/char/Makefile
+--- linux-2.6.18.8/drivers/xen/char/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/char/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1 @@
+obj-$(CONFIG_XEN_DEVMEM) := mem.o
-diff -rpuN linux-2.6.18.8/drivers/xen/char/mem.c linux-2.6.18-xen-3.2.0/drivers/xen/char/mem.c
---- linux-2.6.18.8/drivers/xen/char/mem.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/char/mem.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/char/mem.c linux-2.6.18-xen-3.3.0/drivers/xen/char/mem.c
+--- linux-2.6.18.8/drivers/xen/char/mem.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/char/mem.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,190 @@
+/*
+ * Originally from linux/drivers/char/mem.c
@@ -84147,15 +128889,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/char/mem.c linux-2.6.18-xen-3.2.0/drivers/
+ .mmap = xen_mmap_mem,
+ .open = open_mem,
+};
-diff -rpuN linux-2.6.18.8/drivers/xen/console/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/console/Makefile
---- linux-2.6.18.8/drivers/xen/console/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/console/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,2 @@
-+
-+obj-y := console.o xencons_ring.o
-diff -rpuN linux-2.6.18.8/drivers/xen/console/console.c linux-2.6.18-xen-3.2.0/drivers/xen/console/console.c
---- linux-2.6.18.8/drivers/xen/console/console.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/console/console.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/console/console.c linux-2.6.18-xen-3.3.0/drivers/xen/console/console.c
+--- linux-2.6.18.8/drivers/xen/console/console.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/console/console.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,731 @@
+/******************************************************************************
+ * console.c
@@ -84888,9 +129624,15 @@ diff -rpuN linux-2.6.18.8/drivers/xen/console/console.c linux-2.6.18-xen-3.2.0/d
+module_init(xencons_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/console/xencons_ring.c linux-2.6.18-xen-3.2.0/drivers/xen/console/xencons_ring.c
---- linux-2.6.18.8/drivers/xen/console/xencons_ring.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/console/xencons_ring.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/console/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/console/Makefile
+--- linux-2.6.18.8/drivers/xen/console/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/console/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2 @@
++
++obj-y := console.o xencons_ring.o
+diff -rpuN linux-2.6.18.8/drivers/xen/console/xencons_ring.c linux-2.6.18-xen-3.3.0/drivers/xen/console/xencons_ring.c
+--- linux-2.6.18.8/drivers/xen/console/xencons_ring.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/console/xencons_ring.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,143 @@
+/*
+ * This program is free software; you can redistribute it and/or
@@ -85035,26 +129777,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/console/xencons_ring.c linux-2.6.18-xen-3.
+{
+ (void)xencons_ring_init();
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/core/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/core/Makefile
---- linux-2.6.18.8/drivers/xen/core/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,13 @@
-+#
-+# Makefile for the linux kernel.
-+#
-+
-+obj-y := evtchn.o gnttab.o features.o reboot.o machine_reboot.o firmware.o
-+
-+obj-$(CONFIG_PROC_FS) += xen_proc.o
-+obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor_sysfs.o
-+obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
-+obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
-+obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o
-+obj-$(CONFIG_KEXEC) += machine_kexec.o
-+obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
-diff -rpuN linux-2.6.18.8/drivers/xen/core/cpu_hotplug.c linux-2.6.18-xen-3.2.0/drivers/xen/core/cpu_hotplug.c
---- linux-2.6.18.8/drivers/xen/core/cpu_hotplug.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/cpu_hotplug.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/core/cpu_hotplug.c linux-2.6.18-xen-3.3.0/drivers/xen/core/cpu_hotplug.c
+--- linux-2.6.18.8/drivers/xen/core/cpu_hotplug.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/cpu_hotplug.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,173 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
@@ -85229,10 +129954,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/cpu_hotplug.c linux-2.6.18-xen-3.2.0/
+{
+ xenbus_allowed_cpumask = cpu_present_map;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/core/evtchn.c linux-2.6.18-xen-3.2.0/drivers/xen/core/evtchn.c
---- linux-2.6.18.8/drivers/xen/core/evtchn.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/evtchn.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,1064 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/core/evtchn.c linux-2.6.18-xen-3.3.0/drivers/xen/core/evtchn.c
+--- linux-2.6.18.8/drivers/xen/core/evtchn.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/evtchn.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1061 @@
+/******************************************************************************
+ * evtchn.c
+ *
@@ -85435,9 +130160,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/evtchn.c linux-2.6.18-xen-3.2.0/drive
+ (regs)->IRQ_REG = ~(irq); \
+ do_IRQ((regs)); \
+} while (0)
-+#elif defined (__powerpc__)
-+#define do_IRQ(irq, regs) __do_IRQ(irq, regs)
-+static inline void exit_idle(void) {}
+#endif
+
+/* Xen will never allocate port zero for any purpose. */
@@ -85481,7 +130203,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/evtchn.c linux-2.6.18-xen-3.2.0/drive
+
+#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
+ /* Clear master flag /before/ clearing selector flag. */
-+ rmb();
++ wmb();
+#endif
+ l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
+
@@ -86297,9 +131019,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/evtchn.c linux-2.6.18-xen-3.2.0/drive
+ irq_desc[pirq_to_irq(i)].chip = &pirq_type;
+ }
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/core/features.c linux-2.6.18-xen-3.2.0/drivers/xen/core/features.c
---- linux-2.6.18.8/drivers/xen/core/features.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/features.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/core/features.c linux-2.6.18-xen-3.3.0/drivers/xen/core/features.c
+--- linux-2.6.18.8/drivers/xen/core/features.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/features.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,34 @@
+/******************************************************************************
+ * features.c
@@ -86335,9 +131057,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/features.c linux-2.6.18-xen-3.2.0/dri
+ xen_features[i*32+j] = !!(fi.submap & 1<<j);
+ }
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/core/firmware.c linux-2.6.18-xen-3.2.0/drivers/xen/core/firmware.c
---- linux-2.6.18.8/drivers/xen/core/firmware.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/firmware.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/core/firmware.c linux-2.6.18-xen-3.3.0/drivers/xen/core/firmware.c
+--- linux-2.6.18.8/drivers/xen/core/firmware.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/firmware.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,74 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
@@ -86413,10 +131135,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/firmware.c linux-2.6.18-xen-3.2.0/dri
+ memset(edid_info.dummy, 0x13, sizeof(edid_info.dummy));
+#endif
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drivers/xen/core/gnttab.c
---- linux-2.6.18.8/drivers/xen/core/gnttab.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/gnttab.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,766 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.3.0/drivers/xen/core/gnttab.c
+--- linux-2.6.18.8/drivers/xen/core/gnttab.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/gnttab.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,769 @@
+/******************************************************************************
+ * gnttab.c
+ *
@@ -86471,7 +131193,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+/* External tools reserve first few grant table entries. */
+#define NR_RESERVED_ENTRIES 8
+#define GNTTAB_LIST_END 0xffffffff
-+#define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(grant_entry_t))
++#define ENTRIES_PER_GRANT_FRAME (PAGE_SIZE / sizeof(grant_entry_t))
+
+static grant_ref_t **gnttab_list;
+static unsigned int nr_grant_frames;
@@ -86489,6 +131211,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+#define RPP (PAGE_SIZE / sizeof(grant_ref_t))
+#define gnttab_entry(entry) (gnttab_list[(entry) / RPP][(entry) % RPP])
+
++#define nr_freelist_frames(grant_frames) \
++ (((grant_frames) * ENTRIES_PER_GRANT_FRAME + RPP - 1) / RPP)
++
+static int get_free_entries(int count)
+{
+ unsigned long flags;
@@ -86791,24 +131516,25 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+static int grow_gnttab_list(unsigned int more_frames)
+{
+ unsigned int new_nr_grant_frames, extra_entries, i;
++ unsigned int nr_glist_frames, new_nr_glist_frames;
+
+ new_nr_grant_frames = nr_grant_frames + more_frames;
-+ extra_entries = more_frames * GREFS_PER_GRANT_FRAME;
++ extra_entries = more_frames * ENTRIES_PER_GRANT_FRAME;
+
-+ for (i = nr_grant_frames; i < new_nr_grant_frames; i++)
-+ {
++ nr_glist_frames = nr_freelist_frames(nr_grant_frames);
++ new_nr_glist_frames = nr_freelist_frames(new_nr_grant_frames);
++ for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
+ gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
+ if (!gnttab_list[i])
+ goto grow_nomem;
+ }
+
-+
-+ for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
-+ i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
++ for (i = ENTRIES_PER_GRANT_FRAME * nr_grant_frames;
++ i < ENTRIES_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
+ gnttab_entry(i) = i + 1;
+
+ gnttab_entry(i) = gnttab_free_head;
-+ gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
++ gnttab_free_head = ENTRIES_PER_GRANT_FRAME * nr_grant_frames;
+ gnttab_free_count += extra_entries;
+
+ nr_grant_frames = new_nr_grant_frames;
@@ -86818,7 +131544,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+ return 0;
+
+grow_nomem:
-+ for ( ; i >= nr_grant_frames; i--)
++ for ( ; i >= nr_glist_frames; i--)
+ free_page((unsigned long) gnttab_list[i]);
+ return -ENOMEM;
+}
@@ -87118,8 +131844,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+ unsigned int cur, extra;
+
+ cur = nr_grant_frames;
-+ extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
-+ GREFS_PER_GRANT_FRAME);
++ extra = ((req_entries + (ENTRIES_PER_GRANT_FRAME-1)) /
++ ENTRIES_PER_GRANT_FRAME);
+ if (cur + extra > max_nr_grant_frames())
+ return -ENOSPC;
+
@@ -87132,7 +131858,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+int __devinit gnttab_init(void)
+{
+ int i;
-+ unsigned int max_nr_glist_frames;
++ unsigned int max_nr_glist_frames, nr_glist_frames;
+ unsigned int nr_init_grefs;
+
+ if (!is_running_on_xen())
@@ -87144,16 +131870,15 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+ /* Determine the maximum number of frames required for the
+ * grant reference free list on the current hypervisor.
+ */
-+ max_nr_glist_frames = (boot_max_nr_grant_frames *
-+ GREFS_PER_GRANT_FRAME /
-+ (PAGE_SIZE / sizeof(grant_ref_t)));
++ max_nr_glist_frames = nr_freelist_frames(boot_max_nr_grant_frames);
+
+ gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
+ GFP_KERNEL);
+ if (gnttab_list == NULL)
+ return -ENOMEM;
+
-+ for (i = 0; i < nr_grant_frames; i++) {
++ nr_glist_frames = nr_freelist_frames(nr_grant_frames);
++ for (i = 0; i < nr_glist_frames; i++) {
+ gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
+ if (gnttab_list[i] == NULL)
+ goto ini_nomem;
@@ -87162,7 +131887,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+ if (gnttab_resume() < 0)
+ return -ENODEV;
+
-+ nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
++ nr_init_grefs = nr_grant_frames * ENTRIES_PER_GRANT_FRAME;
+
+ for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
+ gnttab_entry(i) = i + 1;
@@ -87183,9 +131908,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/gnttab.c linux-2.6.18-xen-3.2.0/drive
+#ifdef CONFIG_XEN
+core_initcall(gnttab_init);
+#endif
-diff -rpuN linux-2.6.18.8/drivers/xen/core/hypervisor_sysfs.c linux-2.6.18-xen-3.2.0/drivers/xen/core/hypervisor_sysfs.c
---- linux-2.6.18.8/drivers/xen/core/hypervisor_sysfs.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/hypervisor_sysfs.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/core/hypervisor_sysfs.c linux-2.6.18-xen-3.3.0/drivers/xen/core/hypervisor_sysfs.c
+--- linux-2.6.18.8/drivers/xen/core/hypervisor_sysfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/hypervisor_sysfs.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,57 @@
+/*
+ * copyright (c) 2006 IBM Corporation
@@ -87244,10 +131969,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/hypervisor_sysfs.c linux-2.6.18-xen-3
+}
+
+device_initcall(hypervisor_subsys_init);
-diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_kexec.c linux-2.6.18-xen-3.2.0/drivers/xen/core/machine_kexec.c
---- linux-2.6.18.8/drivers/xen/core/machine_kexec.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/machine_kexec.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,189 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_kexec.c linux-2.6.18-xen-3.3.0/drivers/xen/core/machine_kexec.c
+--- linux-2.6.18.8/drivers/xen/core/machine_kexec.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/machine_kexec.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,207 @@
+/*
+ * drivers/xen/core/machine_kexec.c
+ * handle transition of Linux booting another kernel
@@ -87260,11 +131985,18 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_kexec.c linux-2.6.18-xen-3.2.
+
+extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki,
+ struct kimage *image);
++extern int machine_kexec_setup_resources(struct resource *hypervisor,
++ struct resource *phys_cpus,
++ int nr_phys_cpus);
++extern void machine_kexec_register_resources(struct resource *res);
+
+static int __initdata xen_max_nr_phys_cpus;
+static struct resource xen_hypervisor_res;
+static struct resource *xen_phys_cpus;
+
++size_t vmcoreinfo_size_xen;
++unsigned long paddr_vmcoreinfo_xen;
++
+void __init xen_machine_kexec_setup_resources(void)
+{
+ xen_kexec_range_t range;
@@ -87335,13 +132067,29 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_kexec.c linux-2.6.18-xen-3.2.
+ range.range = KEXEC_RANGE_MA_CRASH;
+
+ if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
-+ return;
++ goto err;
+
+ if (range.size) {
+ crashk_res.start = range.start;
+ crashk_res.end = range.start + range.size - 1;
+ }
+
++ /* get physical address of vmcoreinfo */
++ memset(&range, 0, sizeof(range));
++ range.range = KEXEC_RANGE_MA_VMCOREINFO;
++
++ if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
++ return;
++
++ if (range.size) {
++ paddr_vmcoreinfo_xen = range.start;
++ vmcoreinfo_size_xen = range.size;
++ }
++
++ if (machine_kexec_setup_resources(&xen_hypervisor_res, xen_phys_cpus,
++ xen_max_nr_phys_cpus))
++ goto err;
++
+ return;
+
+ err:
@@ -87356,13 +132104,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_kexec.c linux-2.6.18-xen-3.2.
+
+void __init xen_machine_kexec_register_resources(struct resource *res)
+{
-+ int k;
-+
+ request_resource(res, &xen_hypervisor_res);
-+
-+ for (k = 0; k < xen_max_nr_phys_cpus; k++)
-+ request_resource(&xen_hypervisor_res, xen_phys_cpus + k);
-+
++ machine_kexec_register_resources(res);
+}
+
+static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
@@ -87437,10 +132180,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_kexec.c linux-2.6.18-xen-3.2.
+ * tab-width: 8
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_reboot.c linux-2.6.18-xen-3.2.0/drivers/xen/core/machine_reboot.c
---- linux-2.6.18.8/drivers/xen/core/machine_reboot.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/machine_reboot.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,242 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_reboot.c linux-2.6.18-xen-3.3.0/drivers/xen/core/machine_reboot.c
+--- linux-2.6.18.8/drivers/xen/core/machine_reboot.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/machine_reboot.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,247 @@
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
@@ -87572,13 +132315,18 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_reboot.c linux-2.6.18-xen-3.2
+
+#endif
+
-+static int take_machine_down(void *p_fast_suspend)
++struct suspend {
++ int fast_suspend;
++ void (*resume_notifier)(int);
++};
++
++static int take_machine_down(void *_suspend)
+{
-+ int fast_suspend = *(int *)p_fast_suspend;
++ struct suspend *suspend = _suspend;
+ int suspend_cancelled, err;
+ extern void time_resume(void);
+
-+ if (fast_suspend) {
++ if (suspend->fast_suspend) {
+ BUG_ON(!irqs_disabled());
+ } else {
+ BUG_ON(irqs_disabled());
@@ -87611,6 +132359,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_reboot.c linux-2.6.18-xen-3.2
+ */
+ suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+
++ suspend->resume_notifier(suspend_cancelled);
+ post_suspend(suspend_cancelled);
+ gnttab_resume();
+ if (!suspend_cancelled) {
@@ -87621,27 +132370,23 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_reboot.c linux-2.6.18-xen-3.2
+ * We do it here just in case, but there's no need if we are
+ * in fast-suspend mode as that implies a new enough Xen.
+ */
-+ if (!fast_suspend) {
-+ struct mmuext_op op;
-+ op.cmd = MMUEXT_NEW_USER_BASEPTR;
-+ op.arg1.mfn = pfn_to_mfn(__pa(__user_pgd(
-+ current->active_mm->pgd)) >> PAGE_SHIFT);
-+ if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
-+ BUG();
-+ }
++ if (!suspend->fast_suspend)
++ xen_new_user_pt(__pa(__user_pgd(
++ current->active_mm->pgd)));
+#endif
+ }
+ time_resume();
+
-+ if (!fast_suspend)
++ if (!suspend->fast_suspend)
+ local_irq_enable();
+
+ return suspend_cancelled;
+}
+
-+int __xen_suspend(int fast_suspend)
++int __xen_suspend(int fast_suspend, void (*resume_notifier)(int))
+{
+ int err, suspend_cancelled;
++ struct suspend suspend;
+
+ BUG_ON(smp_processor_id() != 0);
+ BUG_ON(in_interrupt());
@@ -87658,13 +132403,16 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_reboot.c linux-2.6.18-xen-3.2
+ if (num_possible_cpus() == 1)
+ fast_suspend = 0;
+
++ suspend.fast_suspend = fast_suspend;
++ suspend.resume_notifier = resume_notifier;
++
+ if (fast_suspend) {
+ xenbus_suspend();
-+ err = stop_machine_run(take_machine_down, &fast_suspend, 0);
++ err = stop_machine_run(take_machine_down, &suspend, 0);
+ if (err < 0)
+ xenbus_suspend_cancel();
+ } else {
-+ err = take_machine_down(&fast_suspend);
++ err = take_machine_down(&suspend);
+ }
+
+ if (err < 0)
@@ -87683,10 +132431,99 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/machine_reboot.c linux-2.6.18-xen-3.2
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drivers/xen/core/reboot.c
---- linux-2.6.18.8/drivers/xen/core/reboot.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/reboot.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,246 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/core/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/core/Makefile
+--- linux-2.6.18.8/drivers/xen/core/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,14 @@
++#
++# Makefile for the linux kernel.
++#
++
++obj-y := evtchn.o gnttab.o features.o reboot.o machine_reboot.o firmware.o
++
++obj-$(CONFIG_PCI) += pci.o
++obj-$(CONFIG_PROC_FS) += xen_proc.o
++obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor_sysfs.o
++obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
++obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
++obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o
++obj-$(CONFIG_KEXEC) += machine_kexec.o
++obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
+diff -rpuN linux-2.6.18.8/drivers/xen/core/pci.c linux-2.6.18-xen-3.3.0/drivers/xen/core/pci.c
+--- linux-2.6.18.8/drivers/xen/core/pci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/pci.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,67 @@
++/*
++ * vim:shiftwidth=8:noexpandtab
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <xen/interface/physdev.h>
++
++static int (*pci_bus_probe)(struct device *dev);
++static int (*pci_bus_remove)(struct device *dev);
++
++static int pci_bus_probe_wrapper(struct device *dev)
++{
++ int r;
++ struct pci_dev *pci_dev = to_pci_dev(dev);
++ struct physdev_manage_pci manage_pci;
++ manage_pci.bus = pci_dev->bus->number;
++ manage_pci.devfn = pci_dev->devfn;
++
++ r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add, &manage_pci);
++ if (r && r != -ENOSYS)
++ return r;
++
++ r = pci_bus_probe(dev);
++ if (r) {
++ int ret;
++
++ ret = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
++ &manage_pci);
++ WARN_ON(ret && ret != -ENOSYS);
++ }
++
++ return r;
++}
++
++static int pci_bus_remove_wrapper(struct device *dev)
++{
++ int r;
++ struct pci_dev *pci_dev = to_pci_dev(dev);
++ struct physdev_manage_pci manage_pci;
++ manage_pci.bus = pci_dev->bus->number;
++ manage_pci.devfn = pci_dev->devfn;
++
++ r = pci_bus_remove(dev);
++ /* dev and pci_dev are no longer valid!! */
++
++ WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
++ &manage_pci));
++ return r;
++}
++
++static int __init hook_pci_bus(void)
++{
++ if (!is_running_on_xen() || !is_initial_xendomain())
++ return 0;
++
++ pci_bus_probe = pci_bus_type.probe;
++ pci_bus_type.probe = pci_bus_probe_wrapper;
++
++ pci_bus_remove = pci_bus_type.remove;
++ pci_bus_type.remove = pci_bus_remove_wrapper;
++
++ return 0;
++}
++
++core_initcall(hook_pci_bus);
+diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.3.0/drivers/xen/core/reboot.c
+--- linux-2.6.18.8/drivers/xen/core/reboot.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/reboot.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,335 @@
+#define __KERNEL_SYSCALLS__
+#include <linux/version.h>
+#include <linux/kernel.h>
@@ -87696,6 +132533,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drive
+#include <linux/sysrq.h>
+#include <asm/hypervisor.h>
+#include <xen/xenbus.h>
++#include <xen/evtchn.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
@@ -87709,23 +132547,24 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drive
+#define SHUTDOWN_INVALID -1
+#define SHUTDOWN_POWEROFF 0
+#define SHUTDOWN_SUSPEND 2
-+/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
-+ * report a crash, not be instructed to crash!
-+ * HALT is the same as POWEROFF, as far as we're concerned. The tools use
-+ * the distinction when we return the reason code to them.
-+ */
++#define SHUTDOWN_RESUMING 3
+#define SHUTDOWN_HALT 4
+
+/* Ignore multiple shutdown requests. */
+static int shutting_down = SHUTDOWN_INVALID;
+
++/* Was last suspend request cancelled? */
++static int suspend_cancelled;
++
+/* Can we leave APs online when we suspend? */
+static int fast_suspend;
+
+static void __shutdown_handler(void *unused);
+static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
+
-+int __xen_suspend(int fast_suspend);
++static int setup_suspend_evtchn(void);
++
++int __xen_suspend(int fast_suspend, void (*resume_notifier)(int));
+
+static int shutdown_process(void *__unused)
+{
@@ -87754,24 +132593,78 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drive
+ return 0;
+}
+
++static void xen_resume_notifier(int _suspend_cancelled)
++{
++ int old_state = xchg(&shutting_down, SHUTDOWN_RESUMING);
++ BUG_ON(old_state != SHUTDOWN_SUSPEND);
++ suspend_cancelled = _suspend_cancelled;
++}
++
+static int xen_suspend(void *__unused)
+{
-+ int err;
++ int err, old_state;
+
+ daemonize("suspend");
+ err = set_cpus_allowed(current, cpumask_of_cpu(0));
+ if (err) {
+ printk(KERN_ERR "Xen suspend can't run on CPU0 (%d)\n", err);
-+ goto out;
++ goto fail;
+ }
+
-+ err = __xen_suspend(fast_suspend);
-+ if (err)
-+ printk(KERN_ERR "Xen suspend failed (%d)\n", err);
++ do {
++ err = __xen_suspend(fast_suspend, xen_resume_notifier);
++ if (err) {
++ printk(KERN_ERR "Xen suspend failed (%d)\n", err);
++ goto fail;
++ }
++ if (!suspend_cancelled)
++ setup_suspend_evtchn();
++ old_state = cmpxchg(
++ &shutting_down, SHUTDOWN_RESUMING, SHUTDOWN_INVALID);
++ } while (old_state == SHUTDOWN_SUSPEND);
++
++ switch (old_state) {
++ case SHUTDOWN_INVALID:
++ case SHUTDOWN_SUSPEND:
++ BUG();
++ case SHUTDOWN_RESUMING:
++ break;
++ default:
++ schedule_work(&shutdown_work);
++ break;
++ }
+
-+ out:
-+ shutting_down = SHUTDOWN_INVALID;
+ return 0;
++
++ fail:
++ old_state = xchg(&shutting_down, SHUTDOWN_INVALID);
++ BUG_ON(old_state != SHUTDOWN_SUSPEND);
++ return 0;
++}
++
++static void switch_shutdown_state(int new_state)
++{
++ int prev_state, old_state = SHUTDOWN_INVALID;
++
++ /* We only drive shutdown_state into an active state. */
++ if (new_state == SHUTDOWN_INVALID)
++ return;
++
++ do {
++ /* We drop this transition if already in an active state. */
++ if ((old_state != SHUTDOWN_INVALID) &&
++ (old_state != SHUTDOWN_RESUMING))
++ return;
++ /* Attempt to transition. */
++ prev_state = old_state;
++ old_state = cmpxchg(&shutting_down, old_state, new_state);
++ } while (old_state != prev_state);
++
++ /* Either we kick off the work, or we leave it to xen_suspend(). */
++ if (old_state == SHUTDOWN_INVALID)
++ schedule_work(&shutdown_work);
++ else
++ BUG_ON(old_state != SHUTDOWN_RESUMING);
+}
+
+static void __shutdown_handler(void *unused)
@@ -87795,9 +132688,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drive
+ extern void ctrl_alt_del(void);
+ char *str;
+ struct xenbus_transaction xbt;
-+ int err;
++ int err, new_state = SHUTDOWN_INVALID;
+
-+ if (shutting_down != SHUTDOWN_INVALID)
++ if ((shutting_down != SHUTDOWN_INVALID) &&
++ (shutting_down != SHUTDOWN_RESUMING))
+ return;
+
+ again:
@@ -87821,20 +132715,17 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drive
+ }
+
+ if (strcmp(str, "poweroff") == 0)
-+ shutting_down = SHUTDOWN_POWEROFF;
++ new_state = SHUTDOWN_POWEROFF;
+ else if (strcmp(str, "reboot") == 0)
+ ctrl_alt_del();
+ else if (strcmp(str, "suspend") == 0)
-+ shutting_down = SHUTDOWN_SUSPEND;
++ new_state = SHUTDOWN_SUSPEND;
+ else if (strcmp(str, "halt") == 0)
-+ shutting_down = SHUTDOWN_HALT;
-+ else {
++ new_state = SHUTDOWN_HALT;
++ else
+ printk("Ignoring shutdown request: %s\n", str);
-+ shutting_down = SHUTDOWN_INVALID;
-+ }
+
-+ if (shutting_down != SHUTDOWN_INVALID)
-+ schedule_work(&shutdown_work);
++ switch_shutdown_state(new_state);
+
+ kfree(str);
+}
@@ -87880,6 +132771,34 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drive
+ .callback = sysrq_handler
+};
+
++static irqreturn_t suspend_int(int irq, void* dev_id, struct pt_regs *ptregs)
++{
++ switch_shutdown_state(SHUTDOWN_SUSPEND);
++ return IRQ_HANDLED;
++}
++
++static int setup_suspend_evtchn(void)
++{
++ static int irq;
++ int port;
++ char portstr[16];
++
++ if (irq > 0)
++ unbind_from_irqhandler(irq, NULL);
++
++ irq = bind_listening_port_to_irqhandler(0, suspend_int, 0, "suspend",
++ NULL);
++ if (irq <= 0)
++ return -1;
++
++ port = irq_to_evtchn_port(irq);
++ printk(KERN_INFO "suspend: event channel %d\n", port);
++ sprintf(portstr, "%d", port);
++ xenbus_write(XBT_NIL, "device/suspend", "event-channel", portstr);
++
++ return 0;
++}
++
+static int setup_shutdown_watcher(void)
+{
+ int err;
@@ -87900,6 +132819,13 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drive
+ return err;
+ }
+
++ /* suspend event channel */
++ err = setup_suspend_evtchn();
++ if (err) {
++ printk(KERN_ERR "Failed to register suspend event channel\n");
++ return err;
++ }
++
+ return 0;
+}
+
@@ -87933,10 +132859,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/reboot.c linux-2.6.18-xen-3.2.0/drive
+}
+
+#endif /* !defined(CONFIG_XEN) */
-diff -rpuN linux-2.6.18.8/drivers/xen/core/smpboot.c linux-2.6.18-xen-3.2.0/drivers/xen/core/smpboot.c
---- linux-2.6.18.8/drivers/xen/core/smpboot.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/smpboot.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,444 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/core/smpboot.c linux-2.6.18-xen-3.3.0/drivers/xen/core/smpboot.c
+--- linux-2.6.18.8/drivers/xen/core/smpboot.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/smpboot.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,464 @@
+/*
+ * Xen SMP booting functions
+ *
@@ -88197,17 +133123,28 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/smpboot.c linux-2.6.18-xen-3.2.0/driv
+{
+ unsigned int cpu;
+ struct task_struct *idle;
++ int apicid, acpiid;
++ struct vcpu_get_physid cpu_id;
+#ifdef __x86_64__
+ struct desc_ptr *gdt_descr;
+#else
+ struct Xgt_desc_struct *gdt_descr;
+#endif
+
-+ boot_cpu_data.apicid = 0;
++ apicid = 0;
++ if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, 0, &cpu_id) == 0) {
++ apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
++ acpiid = xen_vcpu_physid_to_x86_acpiid(cpu_id.phys_id);
++#ifdef CONFIG_ACPI
++ if (acpiid != 0xff)
++ x86_acpiid_to_apicid[acpiid] = apicid;
++#endif
++ }
++ boot_cpu_data.apicid = apicid;
+ cpu_data[0] = boot_cpu_data;
+
-+ cpu_2_logical_apicid[0] = 0;
-+ x86_cpu_to_apicid[0] = 0;
++ cpu_2_logical_apicid[0] = apicid;
++ x86_cpu_to_apicid[0] = apicid;
+
+ current_thread_info()->cpu = 0;
+
@@ -88251,11 +133188,20 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/smpboot.c linux-2.6.18-xen-3.2.0/driv
+ (void *)gdt_descr->address,
+ XENFEAT_writable_descriptor_tables);
+
++ apicid = cpu;
++ if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, cpu, &cpu_id) == 0) {
++ apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
++ acpiid = xen_vcpu_physid_to_x86_acpiid(cpu_id.phys_id);
++#ifdef CONFIG_ACPI
++ if (acpiid != 0xff)
++ x86_acpiid_to_apicid[acpiid] = apicid;
++#endif
++ }
+ cpu_data[cpu] = boot_cpu_data;
-+ cpu_data[cpu].apicid = cpu;
++ cpu_data[cpu].apicid = apicid;
+
-+ cpu_2_logical_apicid[cpu] = cpu;
-+ x86_cpu_to_apicid[cpu] = cpu;
++ cpu_2_logical_apicid[cpu] = apicid;
++ x86_cpu_to_apicid[cpu] = apicid;
+
+ idle = fork_idle(cpu);
+ if (IS_ERR(idle))
@@ -88381,9 +133327,242 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/smpboot.c linux-2.6.18-xen-3.2.0/driv
+ return -EINVAL;
+}
+#endif
-diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_proc.c linux-2.6.18-xen-3.2.0/drivers/xen/core/xen_proc.c
---- linux-2.6.18.8/drivers/xen/core/xen_proc.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/xen_proc.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/core/xencomm.c linux-2.6.18-xen-3.3.0/drivers/xen/core/xencomm.c
+--- linux-2.6.18.8/drivers/xen/core/xencomm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/xencomm.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,229 @@
++/*
++ * 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; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Copyright (C) IBM Corp. 2006
++ *
++ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
++ */
++
++#include <linux/gfp.h>
++#include <linux/mm.h>
++#include <asm/page.h>
++#include <xen/xencomm.h>
++#include <xen/interface/xen.h>
++#ifdef __ia64__
++#include <asm/xen/xencomm.h> /* for is_kern_addr() */
++#endif
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++static int xencomm_init(struct xencomm_desc *desc,
++ void *buffer, unsigned long bytes)
++{
++ unsigned long recorded = 0;
++ int i = 0;
++
++ while ((recorded < bytes) && (i < desc->nr_addrs)) {
++ unsigned long vaddr = (unsigned long)buffer + recorded;
++ unsigned long paddr;
++ int offset;
++ int chunksz;
++
++ offset = vaddr % PAGE_SIZE; /* handle partial pages */
++ chunksz = min(PAGE_SIZE - offset, bytes - recorded);
++
++ paddr = xencomm_vtop(vaddr);
++ if (paddr == ~0UL) {
++ printk("%s: couldn't translate vaddr %lx\n",
++ __func__, vaddr);
++ return -EINVAL;
++ }
++
++ desc->address[i++] = paddr;
++ recorded += chunksz;
++ }
++
++ if (recorded < bytes) {
++ printk("%s: could only translate %ld of %ld bytes\n",
++ __func__, recorded, bytes);
++ return -ENOSPC;
++ }
++
++ /* mark remaining addresses invalid (just for safety) */
++ while (i < desc->nr_addrs)
++ desc->address[i++] = XENCOMM_INVALID;
++
++ desc->magic = XENCOMM_MAGIC;
++
++ return 0;
++}
++
++static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask,
++ void *buffer, unsigned long bytes)
++{
++ struct xencomm_desc *desc;
++ unsigned long buffer_ulong = (unsigned long)buffer;
++ unsigned long start = buffer_ulong & PAGE_MASK;
++ unsigned long end = (buffer_ulong + bytes) | ~PAGE_MASK;
++ unsigned long nr_addrs = (end - start + 1) >> PAGE_SHIFT;
++ unsigned long size = sizeof(*desc) +
++ sizeof(desc->address[0]) * nr_addrs;
++
++ /*
++ * slab allocator returns at least sizeof(void*) aligned pointer.
++ * When sizeof(*desc) > sizeof(void*), struct xencomm_desc might
++ * cross page boundary.
++ */
++ if (sizeof(*desc) > sizeof(void*)) {
++ unsigned long order = get_order(size);
++ desc = (struct xencomm_desc *)__get_free_pages(gfp_mask,
++ order);
++ if (desc == NULL)
++ return NULL;
++
++ desc->nr_addrs =
++ ((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) /
++ sizeof(*desc->address);
++ } else {
++ desc = kmalloc(size, gfp_mask);
++ if (desc == NULL)
++ return NULL;
++
++ desc->nr_addrs = nr_addrs;
++ }
++ return desc;
++}
++
++void xencomm_free(struct xencomm_handle *desc)
++{
++ if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) {
++ struct xencomm_desc *desc__ = (struct xencomm_desc*)desc;
++ if (sizeof(*desc__) > sizeof(void*)) {
++ unsigned long size = sizeof(*desc__) +
++ sizeof(desc__->address[0]) * desc__->nr_addrs;
++ unsigned long order = get_order(size);
++ free_pages((unsigned long)__va(desc), order);
++ } else
++ kfree(__va(desc));
++ }
++}
++
++static int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc **ret, gfp_t gfp_mask)
++{
++ struct xencomm_desc *desc;
++ int rc;
++
++ pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
++
++ if (bytes == 0) {
++ /* don't create a descriptor; Xen recognizes NULL. */
++ BUG_ON(buffer != NULL);
++ *ret = NULL;
++ return 0;
++ }
++
++ BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
++
++ desc = xencomm_alloc(gfp_mask, buffer, bytes);
++ if (!desc) {
++ printk("%s failure\n", "xencomm_alloc");
++ return -ENOMEM;
++ }
++
++ rc = xencomm_init(desc, buffer, bytes);
++ if (rc) {
++ printk("%s failure: %d\n", "xencomm_init", rc);
++ xencomm_free((struct xencomm_handle *)__pa(desc));
++ return rc;
++ }
++
++ *ret = desc;
++ return 0;
++}
++
++/* check if memory address is within VMALLOC region */
++static int is_phys_contiguous(unsigned long addr)
++{
++ if (!is_kernel_addr(addr))
++ return 0;
++
++ return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
++}
++
++static struct xencomm_handle *xencomm_create_inline(void *ptr)
++{
++ unsigned long paddr;
++
++ BUG_ON(!is_phys_contiguous((unsigned long)ptr));
++
++ paddr = (unsigned long)xencomm_pa(ptr);
++ BUG_ON(paddr & XENCOMM_INLINE_FLAG);
++ return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
++}
++
++/* "mini" routine, for stack-based communications: */
++static int xencomm_create_mini(void *buffer,
++ unsigned long bytes, struct xencomm_mini *xc_desc,
++ struct xencomm_desc **ret)
++{
++ int rc = 0;
++ struct xencomm_desc *desc;
++ BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0);
++
++ desc = (void *)xc_desc;
++
++ desc->nr_addrs = XENCOMM_MINI_ADDRS;
++
++ if (!(rc = xencomm_init(desc, buffer, bytes)))
++ *ret = desc;
++
++ return rc;
++}
++
++struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
++{
++ int rc;
++ struct xencomm_desc *desc;
++
++ if (is_phys_contiguous((unsigned long)ptr))
++ return xencomm_create_inline(ptr);
++
++ rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
++
++ if (rc || desc == NULL)
++ return NULL;
++
++ return xencomm_pa(desc);
++}
++
++struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
++ struct xencomm_mini *xc_desc)
++{
++ int rc;
++ struct xencomm_desc *desc = NULL;
++
++ if (is_phys_contiguous((unsigned long)ptr))
++ return xencomm_create_inline(ptr);
++
++ rc = xencomm_create_mini(ptr, bytes, xc_desc,
++ &desc);
++
++ if (rc)
++ return NULL;
++
++ return xencomm_pa(desc);
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_proc.c linux-2.6.18-xen-3.3.0/drivers/xen/core/xen_proc.c
+--- linux-2.6.18.8/drivers/xen/core/xen_proc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/xen_proc.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,23 @@
+
+#include <linux/module.h>
@@ -88408,10 +133587,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_proc.c linux-2.6.18-xen-3.2.0/dri
+}
+
+EXPORT_SYMBOL_GPL(remove_xen_proc_entry);
-diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_sysfs.c linux-2.6.18-xen-3.2.0/drivers/xen/core/xen_sysfs.c
---- linux-2.6.18.8/drivers/xen/core/xen_sysfs.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/xen_sysfs.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,378 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_sysfs.c linux-2.6.18-xen-3.3.0/drivers/xen/core/xen_sysfs.c
+--- linux-2.6.18.8/drivers/xen/core/xen_sysfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/core/xen_sysfs.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,420 @@
+/*
+ * copyright (c) 2006 IBM Corporation
+ * Authored by: Mike D. Day <ncmike@us.ibm.com>
@@ -88429,6 +133608,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_sysfs.c linux-2.6.18-xen-3.2.0/dr
+#include <xen/features.h>
+#include <xen/hypervisor_sysfs.h>
+#include <xen/xenbus.h>
++#include <xen/interface/kexec.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mike D. Day <ncmike@us.ibm.com>");
@@ -88518,6 +133698,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_sysfs.c linux-2.6.18-xen-3.2.0/dr
+{
+ char *vm, *val;
+ int ret;
++ extern int xenstored_ready;
++
++ if (!xenstored_ready)
++ return -EBUSY;
+
+ vm = xenbus_read(XBT_NIL, "vm", "", NULL);
+ if (IS_ERR(vm))
@@ -88744,6 +133928,37 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_sysfs.c linux-2.6.18-xen-3.2.0/dr
+ &xen_properties_group);
+}
+
++#ifdef CONFIG_KEXEC
++
++static ssize_t vmcoreinfo_show(struct hyp_sysfs_attr *attr, char *page)
++{
++ extern size_t vmcoreinfo_size_xen;
++ extern unsigned long paddr_vmcoreinfo_xen;
++
++ return sprintf(page, "%lx %zx\n",
++ paddr_vmcoreinfo_xen, vmcoreinfo_size_xen);
++}
++
++HYPERVISOR_ATTR_RO(vmcoreinfo);
++
++static int __init xen_sysfs_vmcoreinfo_init(void)
++{
++ return sysfs_create_file(&hypervisor_subsys.kset.kobj,
++ &vmcoreinfo_attr.attr);
++}
++
++static void xen_sysfs_vmcoreinfo_destroy(void)
++{
++ sysfs_remove_file(&hypervisor_subsys.kset.kobj, &vmcoreinfo_attr.attr);
++}
++
++#else
++
++#define xen_sysfs_vmcoreinfo_init() 0
++#define xen_sysfs_vmcoreinfo_destroy() ((void)0)
++
++#endif
++
+static int __init hyper_sysfs_init(void)
+{
+ int ret;
@@ -88764,9 +133979,14 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_sysfs.c linux-2.6.18-xen-3.2.0/dr
+ if (ret)
+ goto uuid_out;
+ ret = xen_properties_init();
++ if (ret)
++ goto prop_out;
++ ret = xen_sysfs_vmcoreinfo_init();
+ if (!ret)
+ goto out;
+
++ xen_properties_destroy();
++prop_out:
+ xen_sysfs_uuid_destroy();
+uuid_out:
+ xen_compilation_destroy();
@@ -88780,6 +134000,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_sysfs.c linux-2.6.18-xen-3.2.0/dr
+
+static void __exit hyper_sysfs_exit(void)
+{
++ xen_sysfs_vmcoreinfo_destroy();
+ xen_properties_destroy();
+ xen_compilation_destroy();
+ xen_sysfs_uuid_destroy();
@@ -88790,249 +134011,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/core/xen_sysfs.c linux-2.6.18-xen-3.2.0/dr
+
+module_init(hyper_sysfs_init);
+module_exit(hyper_sysfs_exit);
-diff -rpuN linux-2.6.18.8/drivers/xen/core/xencomm.c linux-2.6.18-xen-3.2.0/drivers/xen/core/xencomm.c
---- linux-2.6.18.8/drivers/xen/core/xencomm.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/core/xencomm.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,229 @@
-+/*
-+ * 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; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * Copyright (C) IBM Corp. 2006
-+ *
-+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
-+ */
-+
-+#include <linux/gfp.h>
-+#include <linux/mm.h>
-+#include <asm/page.h>
-+#include <xen/xencomm.h>
-+#include <xen/interface/xen.h>
-+#ifdef __ia64__
-+#include <asm/xen/xencomm.h> /* for is_kern_addr() */
-+#endif
-+
-+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
-+#include <xen/platform-compat.h>
-+#endif
-+
-+static int xencomm_init(struct xencomm_desc *desc,
-+ void *buffer, unsigned long bytes)
-+{
-+ unsigned long recorded = 0;
-+ int i = 0;
-+
-+ while ((recorded < bytes) && (i < desc->nr_addrs)) {
-+ unsigned long vaddr = (unsigned long)buffer + recorded;
-+ unsigned long paddr;
-+ int offset;
-+ int chunksz;
-+
-+ offset = vaddr % PAGE_SIZE; /* handle partial pages */
-+ chunksz = min(PAGE_SIZE - offset, bytes - recorded);
-+
-+ paddr = xencomm_vtop(vaddr);
-+ if (paddr == ~0UL) {
-+ printk("%s: couldn't translate vaddr %lx\n",
-+ __func__, vaddr);
-+ return -EINVAL;
-+ }
-+
-+ desc->address[i++] = paddr;
-+ recorded += chunksz;
-+ }
-+
-+ if (recorded < bytes) {
-+ printk("%s: could only translate %ld of %ld bytes\n",
-+ __func__, recorded, bytes);
-+ return -ENOSPC;
-+ }
-+
-+ /* mark remaining addresses invalid (just for safety) */
-+ while (i < desc->nr_addrs)
-+ desc->address[i++] = XENCOMM_INVALID;
-+
-+ desc->magic = XENCOMM_MAGIC;
-+
-+ return 0;
-+}
-+
-+static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask,
-+ void *buffer, unsigned long bytes)
-+{
-+ struct xencomm_desc *desc;
-+ unsigned long buffer_ulong = (unsigned long)buffer;
-+ unsigned long start = buffer_ulong & PAGE_MASK;
-+ unsigned long end = (buffer_ulong + bytes) | ~PAGE_MASK;
-+ unsigned long nr_addrs = (end - start + 1) >> PAGE_SHIFT;
-+ unsigned long size = sizeof(*desc) +
-+ sizeof(desc->address[0]) * nr_addrs;
-+
-+ /*
-+ * slab allocator returns at least sizeof(void*) aligned pointer.
-+ * When sizeof(*desc) > sizeof(void*), struct xencomm_desc might
-+ * cross page boundary.
-+ */
-+ if (sizeof(*desc) > sizeof(void*)) {
-+ unsigned long order = get_order(size);
-+ desc = (struct xencomm_desc *)__get_free_pages(gfp_mask,
-+ order);
-+ if (desc == NULL)
-+ return NULL;
-+
-+ desc->nr_addrs =
-+ ((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) /
-+ sizeof(*desc->address);
-+ } else {
-+ desc = kmalloc(size, gfp_mask);
-+ if (desc == NULL)
-+ return NULL;
-+
-+ desc->nr_addrs = nr_addrs;
-+ }
-+ return desc;
-+}
-+
-+void xencomm_free(struct xencomm_handle *desc)
-+{
-+ if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) {
-+ struct xencomm_desc *desc__ = (struct xencomm_desc*)desc;
-+ if (sizeof(*desc__) > sizeof(void*)) {
-+ unsigned long size = sizeof(*desc__) +
-+ sizeof(desc__->address[0]) * desc__->nr_addrs;
-+ unsigned long order = get_order(size);
-+ free_pages((unsigned long)__va(desc), order);
-+ } else
-+ kfree(__va(desc));
-+ }
-+}
-+
-+static int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc **ret, gfp_t gfp_mask)
-+{
-+ struct xencomm_desc *desc;
-+ int rc;
-+
-+ pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
-+
-+ if (bytes == 0) {
-+ /* don't create a descriptor; Xen recognizes NULL. */
-+ BUG_ON(buffer != NULL);
-+ *ret = NULL;
-+ return 0;
-+ }
-+
-+ BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
-+
-+ desc = xencomm_alloc(gfp_mask, buffer, bytes);
-+ if (!desc) {
-+ printk("%s failure\n", "xencomm_alloc");
-+ return -ENOMEM;
-+ }
-+
-+ rc = xencomm_init(desc, buffer, bytes);
-+ if (rc) {
-+ printk("%s failure: %d\n", "xencomm_init", rc);
-+ xencomm_free((struct xencomm_handle *)__pa(desc));
-+ return rc;
-+ }
-+
-+ *ret = desc;
-+ return 0;
-+}
-+
-+/* check if memory address is within VMALLOC region */
-+static int is_phys_contiguous(unsigned long addr)
-+{
-+ if (!is_kernel_addr(addr))
-+ return 0;
-+
-+ return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
-+}
-+
-+static struct xencomm_handle *xencomm_create_inline(void *ptr)
-+{
-+ unsigned long paddr;
-+
-+ BUG_ON(!is_phys_contiguous((unsigned long)ptr));
-+
-+ paddr = (unsigned long)xencomm_pa(ptr);
-+ BUG_ON(paddr & XENCOMM_INLINE_FLAG);
-+ return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
-+}
-+
-+/* "mini" routine, for stack-based communications: */
-+static int xencomm_create_mini(void *buffer,
-+ unsigned long bytes, struct xencomm_mini *xc_desc,
-+ struct xencomm_desc **ret)
-+{
-+ int rc = 0;
-+ struct xencomm_desc *desc;
-+ BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0);
-+
-+ desc = (void *)xc_desc;
-+
-+ desc->nr_addrs = XENCOMM_MINI_ADDRS;
-+
-+ if (!(rc = xencomm_init(desc, buffer, bytes)))
-+ *ret = desc;
-+
-+ return rc;
-+}
-+
-+struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
-+{
-+ int rc;
-+ struct xencomm_desc *desc;
-+
-+ if (is_phys_contiguous((unsigned long)ptr))
-+ return xencomm_create_inline(ptr);
-+
-+ rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
-+
-+ if (rc || desc == NULL)
-+ return NULL;
-+
-+ return xencomm_pa(desc);
-+}
-+
-+struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
-+ struct xencomm_mini *xc_desc)
-+{
-+ int rc;
-+ struct xencomm_desc *desc = NULL;
-+
-+ if (is_phys_contiguous((unsigned long)ptr))
-+ return xencomm_create_inline(ptr);
-+
-+ rc = xencomm_create_mini(ptr, bytes, xc_desc,
-+ &desc);
-+
-+ if (rc)
-+ return NULL;
-+
-+ return xencomm_pa(desc);
-+}
-diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/evtchn/Makefile
---- linux-2.6.18.8/drivers/xen/evtchn/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/evtchn/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,2 @@
-+
-+obj-y := evtchn.o
-diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/evtchn.c linux-2.6.18-xen-3.2.0/drivers/xen/evtchn/evtchn.c
---- linux-2.6.18.8/drivers/xen/evtchn/evtchn.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/evtchn/evtchn.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,556 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/evtchn.c linux-2.6.18-xen-3.3.0/drivers/xen/evtchn/evtchn.c
+--- linux-2.6.18.8/drivers/xen/evtchn/evtchn.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/evtchn/evtchn.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,560 @@
+/******************************************************************************
+ * evtchn.c
+ *
@@ -89119,6 +134101,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/evtchn.c linux-2.6.18-xen-3.2.0/dri
+ if ((u = port_user[port]) != NULL) {
+ if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
+ u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port;
++ wmb(); /* Ensure ring contents visible */
+ if (u->ring_cons == u->ring_prod++) {
+ wake_up_interruptible(&u->evtchn_wait);
+ kill_fasync(&u->evtchn_async_queue,
@@ -89215,6 +134198,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/evtchn.c linux-2.6.18-xen-3.2.0/dri
+ }
+
+ rc = -EFAULT;
++ rmb(); /* Ensure that we see the port before we copy it. */
+ if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
+ ((bytes2 != 0) &&
+ copy_to_user(&buf[bytes1], &u->ring[0], bytes2)))
@@ -89384,6 +134368,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/evtchn.c linux-2.6.18-xen-3.2.0/dri
+
+ port_user[unbind.port] = NULL;
+ mask_evtchn(unbind.port);
++ rebind_evtchn_to_cpu(unbind.port, 0);
+
+ spin_unlock_irq(&port_user_lock);
+
@@ -89493,6 +134478,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/evtchn.c linux-2.6.18-xen-3.2.0/dri
+
+ port_user[i] = NULL;
+ mask_evtchn(i);
++ rebind_evtchn_to_cpu(i, 0);
+
+ close.port = i;
+ ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
@@ -89589,16 +134575,22 @@ diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/evtchn.c linux-2.6.18-xen-3.2.0/dri
+module_exit(evtchn_cleanup);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/fbfront/Makefile
---- linux-2.6.18.8/drivers/xen/fbfront/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/fbfront/Makefile 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/evtchn/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/evtchn/Makefile
+--- linux-2.6.18.8/drivers/xen/evtchn/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/evtchn/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2 @@
++
++obj-y := evtchn.o
+diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/fbfront/Makefile
+--- linux-2.6.18.8/drivers/xen/fbfront/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/fbfront/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,2 @@
+obj-$(CONFIG_XEN_FRAMEBUFFER) := xenfb.o
+obj-$(CONFIG_XEN_KEYBOARD) += xenkbd.o
-diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/drivers/xen/fbfront/xenfb.c
---- linux-2.6.18.8/drivers/xen/fbfront/xenfb.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/fbfront/xenfb.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,758 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.3.0/drivers/xen/fbfront/xenfb.c
+--- linux-2.6.18.8/drivers/xen/fbfront/xenfb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/fbfront/xenfb.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,887 @@
+/*
+ * linux/drivers/video/xenfb.c -- Xen para-virtual frame buffer device
+ *
@@ -89663,15 +134655,21 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ struct xenfb_page *page;
+ unsigned long *mfns;
+ int update_wanted; /* XENFB_TYPE_UPDATE wanted */
++ int feature_resize; /* Backend has resize feature */
++ struct xenfb_resize resize;
++ int resize_dpy;
++ spinlock_t resize_lock;
+
+ struct xenbus_device *xbdev;
+};
+
+/*
-+ * How the locks work together
++ * There are three locks:
++ * spinlock resize_lock protecting resize_dpy and resize
++ * spinlock dirty_lock protecting the dirty rectangle
++ * mutex mm_lock protecting mappings.
+ *
-+ * There are two locks: spinlock dirty_lock protecting the dirty
-+ * rectangle, and mutex mm_lock protecting mappings.
++ * How the dirty and mapping locks work together
+ *
+ * The problem is that dirty rectangle and mappings aren't
+ * independent: the dirty rectangle must cover all faulted pages in
@@ -89730,35 +134728,62 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ *
+ * Oh well, we wont be updating the writes to this page anytime soon.
+ */
++#define MB_ (1024*1024)
++#define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
++
++enum {KPARAM_MEM, KPARAM_WIDTH, KPARAM_HEIGHT, KPARAM_CNT};
++static int video[KPARAM_CNT] = {2, XENFB_WIDTH, XENFB_HEIGHT};
++module_param_array(video, int, NULL, 0);
++MODULE_PARM_DESC(video,
++ "Size of video memory in MB and width,height in pixels, default = (2,800,600)");
+
+static int xenfb_fps = 20;
-+static unsigned long xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
+
+static int xenfb_remove(struct xenbus_device *);
-+static void xenfb_init_shared_page(struct xenfb_info *);
++static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *);
+static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
+static void xenfb_disconnect_backend(struct xenfb_info *);
+
++static void xenfb_send_event(struct xenfb_info *info,
++ union xenfb_out_event *event)
++{
++ __u32 prod;
++
++ prod = info->page->out_prod;
++ /* caller ensures !xenfb_queue_full() */
++ mb(); /* ensure ring space available */
++ XENFB_OUT_RING_REF(info->page, prod) = *event;
++ wmb(); /* ensure ring contents visible */
++ info->page->out_prod = prod + 1;
++
++ notify_remote_via_irq(info->irq);
++}
++
+static void xenfb_do_update(struct xenfb_info *info,
+ int x, int y, int w, int h)
+{
+ union xenfb_out_event event;
-+ __u32 prod;
+
++ memset(&event, 0, sizeof(event));
+ event.type = XENFB_TYPE_UPDATE;
+ event.update.x = x;
+ event.update.y = y;
+ event.update.width = w;
+ event.update.height = h;
+
-+ prod = info->page->out_prod;
+ /* caller ensures !xenfb_queue_full() */
-+ mb(); /* ensure ring space available */
-+ XENFB_OUT_RING_REF(info->page, prod) = event;
-+ wmb(); /* ensure ring contents visible */
-+ info->page->out_prod = prod + 1;
++ xenfb_send_event(info, &event);
++}
+
-+ notify_remote_via_irq(info->irq);
++static void xenfb_do_resize(struct xenfb_info *info)
++{
++ union xenfb_out_event event;
++
++ memset(&event, 0, sizeof(event));
++ event.resize = info->resize;
++
++ /* caller ensures !xenfb_queue_full() */
++ xenfb_send_event(info, &event);
+}
+
+static int xenfb_queue_full(struct xenfb_info *info)
@@ -89810,11 +134835,26 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1);
+}
+
++static void xenfb_handle_resize_dpy(struct xenfb_info *info)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&info->resize_lock, flags);
++ if (info->resize_dpy) {
++ if (!xenfb_queue_full(info)) {
++ info->resize_dpy = 0;
++ xenfb_do_resize(info);
++ }
++ }
++ spin_unlock_irqrestore(&info->resize_lock, flags);
++}
++
+static int xenfb_thread(void *data)
+{
+ struct xenfb_info *info = data;
+
+ while (!kthread_should_stop()) {
++ xenfb_handle_resize_dpy(info);
+ if (info->dirty) {
+ info->dirty = 0;
+ xenfb_update_screen(info);
@@ -90014,6 +135054,57 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ return 0;
+}
+
++static int
++xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
++{
++ struct xenfb_info *xenfb_info;
++ int required_mem_len;
++
++ xenfb_info = info->par;
++
++ if (!xenfb_info->feature_resize) {
++ if (var->xres == video[KPARAM_WIDTH] &&
++ var->yres == video[KPARAM_HEIGHT] &&
++ var->bits_per_pixel == xenfb_info->page->depth) {
++ return 0;
++ }
++ return -EINVAL;
++ }
++
++ /* Can't resize past initial width and height */
++ if (var->xres > video[KPARAM_WIDTH] || var->yres > video[KPARAM_HEIGHT])
++ return -EINVAL;
++
++ required_mem_len = var->xres * var->yres * (xenfb_info->page->depth / 8);
++ if (var->bits_per_pixel == xenfb_info->page->depth &&
++ var->xres <= info->fix.line_length / (XENFB_DEPTH / 8) &&
++ required_mem_len <= info->fix.smem_len) {
++ var->xres_virtual = var->xres;
++ var->yres_virtual = var->yres;
++ return 0;
++ }
++ return -EINVAL;
++}
++
++static int xenfb_set_par(struct fb_info *info)
++{
++ struct xenfb_info *xenfb_info;
++ unsigned long flags;
++
++ xenfb_info = info->par;
++
++ spin_lock_irqsave(&xenfb_info->resize_lock, flags);
++ xenfb_info->resize.type = XENFB_TYPE_RESIZE;
++ xenfb_info->resize.width = info->var.xres;
++ xenfb_info->resize.height = info->var.yres;
++ xenfb_info->resize.stride = info->fix.line_length;
++ xenfb_info->resize.depth = info->var.bits_per_pixel;
++ xenfb_info->resize.offset = 0;
++ xenfb_info->resize_dpy = 1;
++ spin_unlock_irqrestore(&xenfb_info->resize_lock, flags);
++ return 0;
++}
++
+static struct fb_ops xenfb_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = xenfb_setcolreg,
@@ -90021,6 +135112,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ .fb_copyarea = xenfb_copyarea,
+ .fb_imageblit = xenfb_imageblit,
+ .fb_mmap = xenfb_mmap,
++ .fb_check_var = xenfb_check_var,
++ .fb_set_par = xenfb_set_par,
+};
+
+static irqreturn_t xenfb_event_handler(int rq, void *dev_id,
@@ -90051,6 +135144,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+{
+ struct xenfb_info *info;
+ struct fb_info *fb_info;
++ int fb_size;
++ int val;
+ int ret;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -90058,11 +135153,27 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+ return -ENOMEM;
+ }
++
++ /* Limit kernel param videoram amount to what is in xenstore */
++ if (xenbus_scanf(XBT_NIL, dev->otherend, "videoram", "%d", &val) == 1) {
++ if (val < video[KPARAM_MEM])
++ video[KPARAM_MEM] = val;
++ }
++
++ /* If requested res does not fit in available memory, use default */
++ fb_size = video[KPARAM_MEM] * MB_;
++ if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH/8 > fb_size) {
++ video[KPARAM_WIDTH] = XENFB_WIDTH;
++ video[KPARAM_HEIGHT] = XENFB_HEIGHT;
++ fb_size = XENFB_DEFAULT_FB_LEN;
++ }
++
+ dev->dev.driver_data = info;
+ info->xbdev = dev;
+ info->irq = -1;
+ info->x1 = info->y1 = INT_MAX;
+ spin_lock_init(&info->dirty_lock);
++ spin_lock_init(&info->resize_lock);
+ mutex_init(&info->mm_lock);
+ init_waitqueue_head(&info->wq);
+ init_timer(&info->refresh);
@@ -90070,12 +135181,12 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ info->refresh.data = (unsigned long)info;
+ INIT_LIST_HEAD(&info->mappings);
+
-+ info->fb = vmalloc(xenfb_mem_len);
++ info->fb = vmalloc(fb_size);
+ if (info->fb == NULL)
+ goto error_nomem;
-+ memset(info->fb, 0, xenfb_mem_len);
++ memset(info->fb, 0, fb_size);
+
-+ info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ info->pages = kmalloc(sizeof(struct page *) * info->nr_pages,
+ GFP_KERNEL);
@@ -90091,8 +135202,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ if (!info->page)
+ goto error_nomem;
+
-+ xenfb_init_shared_page(info);
-+
+ fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
+ /* see fishy hackery below */
+ if (fb_info == NULL)
@@ -90105,9 +135214,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ fb_info->screen_base = info->fb;
+
+ fb_info->fbops = &xenfb_fb_ops;
-+ fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
-+ fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
-+ fb_info->var.bits_per_pixel = info->page->depth;
++ fb_info->var.xres_virtual = fb_info->var.xres = video[KPARAM_WIDTH];
++ fb_info->var.yres_virtual = fb_info->var.yres = video[KPARAM_HEIGHT];
++ fb_info->var.bits_per_pixel = XENFB_DEPTH;
+
+ fb_info->var.red = (struct fb_bitfield){16, 8, 0};
+ fb_info->var.green = (struct fb_bitfield){8, 8, 0};
@@ -90119,9 +135228,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ fb_info->var.vmode = FB_VMODE_NONINTERLACED;
+
+ fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
-+ fb_info->fix.line_length = info->page->line_length;
++ fb_info->fix.line_length = fb_info->var.xres * (XENFB_DEPTH / 8);
+ fb_info->fix.smem_start = 0;
-+ fb_info->fix.smem_len = xenfb_mem_len;
++ fb_info->fix.smem_len = fb_size;
+ strcpy(fb_info->fix.id, "xen");
+ fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+ fb_info->fix.accel = FB_ACCEL_NONE;
@@ -90135,6 +135244,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ goto error;
+ }
+
++ xenfb_init_shared_page(info, fb_info);
++
+ ret = register_framebuffer(fb_info);
+ if (ret) {
+ fb_dealloc_cmap(&info->fb_info->cmap);
@@ -90172,7 +135283,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ struct xenfb_info *info = dev->dev.driver_data;
+
+ xenfb_disconnect_backend(info);
-+ xenfb_init_shared_page(info);
++ xenfb_init_shared_page(info, info->fb_info);
+ return xenfb_connect_backend(dev, info);
+}
+
@@ -90198,9 +135309,11 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ return 0;
+}
+
-+static void xenfb_init_shared_page(struct xenfb_info *info)
++static void xenfb_init_shared_page(struct xenfb_info *info,
++ struct fb_info * fb_info)
+{
+ int i;
++ int epd = PAGE_SIZE / sizeof(info->mfns[0]);
+
+ for (i = 0; i < info->nr_pages; i++)
+ info->pages[i] = vmalloc_to_page(info->fb + i * PAGE_SIZE);
@@ -90208,13 +135321,14 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ for (i = 0; i < info->nr_pages; i++)
+ info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
+
-+ info->page->pd[0] = vmalloc_to_mfn(info->mfns);
-+ info->page->pd[1] = 0;
-+ info->page->width = XENFB_WIDTH;
-+ info->page->height = XENFB_HEIGHT;
-+ info->page->depth = XENFB_DEPTH;
-+ info->page->line_length = (info->page->depth / 8) * info->page->width;
-+ info->page->mem_length = xenfb_mem_len;
++ for (i = 0; i * epd < info->nr_pages; i++)
++ info->page->pd[i] = vmalloc_to_mfn(&info->mfns[i * epd]);
++
++ info->page->width = fb_info->var.xres;
++ info->page->height = fb_info->var.yres;
++ info->page->depth = fb_info->var.bits_per_pixel;
++ info->page->line_length = fb_info->fix.line_length;
++ info->page->mem_length = fb_info->fix.smem_len;
+ info->page->in_cons = info->page->in_prod = 0;
+ info->page->out_cons = info->page->out_prod = 0;
+}
@@ -90288,6 +135402,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ switch (backend_state) {
+ case XenbusStateInitialising:
+ case XenbusStateInitialised:
++ case XenbusStateReconfiguring:
++ case XenbusStateReconfigured:
+ case XenbusStateUnknown:
+ case XenbusStateClosed:
+ break;
@@ -90311,6 +135427,11 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ val = 0;
+ if (val)
+ info->update_wanted = 1;
++
++ if (xenbus_scanf(XBT_NIL, dev->otherend,
++ "feature-resize", "%d", &val) < 0)
++ val = 0;
++ info->feature_resize = val;
+ break;
+
+ case XenbusStateClosing:
@@ -90320,13 +135441,13 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ }
+}
+
-+static struct xenbus_device_id xenfb_ids[] = {
++static const struct xenbus_device_id xenfb_ids[] = {
+ { "vfb" },
+ { "" }
+};
+MODULE_ALIAS("xen:vfb");
+
-+static struct xenbus_driver xenfb = {
++static struct xenbus_driver xenfb_driver = {
+ .name = "vfb",
+ .owner = THIS_MODULE,
+ .ids = xenfb_ids,
@@ -90345,22 +135466,22 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenfb.c linux-2.6.18-xen-3.2.0/dri
+ if (is_initial_xendomain())
+ return -ENODEV;
+
-+ return xenbus_register_frontend(&xenfb);
++ return xenbus_register_frontend(&xenfb_driver);
+}
+
+static void __exit xenfb_cleanup(void)
+{
-+ return xenbus_unregister_driver(&xenfb);
++ return xenbus_unregister_driver(&xenfb_driver);
+}
+
+module_init(xenfb_init);
+module_exit(xenfb_cleanup);
+
+MODULE_LICENSE("GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.2.0/drivers/xen/fbfront/xenkbd.c
---- linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/fbfront/xenkbd.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,346 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.3.0/drivers/xen/fbfront/xenkbd.c
+--- linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/fbfront/xenkbd.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,354 @@
+/*
+ * linux/drivers/input/keyboard/xenkbd.c -- Xen para-virtual input device
+ *
@@ -90416,7 +135537,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.2.0/dr
+ __u32 cons, prod;
+
+ prod = page->in_prod;
-+ if (prod == page->out_cons)
++ if (prod == page->in_cons)
+ return IRQ_HANDLED;
+ rmb(); /* ensure we see ring contents up to prod */
+ for (cons = page->in_cons; cons != prod; cons++) {
@@ -90427,13 +135548,11 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.2.0/dr
+ dev = info->ptr;
+ switch (event->type) {
+ case XENKBD_TYPE_MOTION:
-+ if ( event->motion.rel_z == 1 || event->motion.rel_z == -1 ) {
-+ input_report_rel(dev, REL_WHEEL, 0 - event->motion.rel_z);
-+ }
-+ else {
-+ input_report_rel(dev, REL_X, event->motion.rel_x);
-+ input_report_rel(dev, REL_Y, event->motion.rel_y);
-+ }
++ if (event->motion.rel_z)
++ input_report_rel(dev, REL_WHEEL,
++ -event->motion.rel_z);
++ input_report_rel(dev, REL_X, event->motion.rel_x);
++ input_report_rel(dev, REL_Y, event->motion.rel_y);
+ break;
+ case XENKBD_TYPE_KEY:
+ dev = NULL;
@@ -90449,13 +135568,11 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.2.0/dr
+ event->key.keycode);
+ break;
+ case XENKBD_TYPE_POS:
-+ if ( event->pos.abs_z == 1 || event->pos.abs_z == -1 ) {
-+ input_report_rel(dev, REL_WHEEL, 0 - event->pos.abs_z);
-+ }
-+ else {
-+ input_report_abs(dev, ABS_X, event->pos.abs_x);
-+ input_report_abs(dev, ABS_Y, event->pos.abs_y);
-+ }
++ if (event->pos.rel_z)
++ input_report_rel(dev, REL_WHEEL,
++ -event->pos.rel_z);
++ input_report_abs(dev, ABS_X, event->pos.abs_x);
++ input_report_abs(dev, ABS_Y, event->pos.abs_y);
+ break;
+ }
+ if (dev)
@@ -90635,6 +135752,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.2.0/dr
+ switch (backend_state) {
+ case XenbusStateInitialising:
+ case XenbusStateInitialised:
++ case XenbusStateReconfiguring:
++ case XenbusStateReconfigured:
+ case XenbusStateUnknown:
+ case XenbusStateClosed:
+ break;
@@ -90662,6 +135781,16 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.2.0/dr
+ */
+ if (dev->state != XenbusStateConnected)
+ goto InitWait; /* no InitWait seen yet, fudge it */
++
++ /* Set input abs params to match backend screen res */
++ if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
++ "width", "%d", &val) > 0 )
++ input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
++
++ if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
++ "height", "%d", &val) > 0 )
++ input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
++
+ break;
+
+ case XenbusStateClosing:
@@ -90670,13 +135799,13 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.2.0/dr
+ }
+}
+
-+static struct xenbus_device_id xenkbd_ids[] = {
++static const struct xenbus_device_id xenkbd_ids[] = {
+ { "vkbd" },
+ { "" }
+};
+MODULE_ALIAS("xen:vkbd");
+
-+static struct xenbus_driver xenkbd = {
++static struct xenbus_driver xenkbd_driver = {
+ .name = "vkbd",
+ .owner = THIS_MODULE,
+ .ids = xenkbd_ids,
@@ -90695,27 +135824,22 @@ diff -rpuN linux-2.6.18.8/drivers/xen/fbfront/xenkbd.c linux-2.6.18-xen-3.2.0/dr
+ if (is_initial_xendomain())
+ return -ENODEV;
+
-+ return xenbus_register_frontend(&xenkbd);
++ return xenbus_register_frontend(&xenkbd_driver);
+}
+
+static void __exit xenkbd_cleanup(void)
+{
-+ return xenbus_unregister_driver(&xenkbd);
++ return xenbus_unregister_driver(&xenkbd_driver);
+}
+
+module_init(xenkbd_init);
+module_exit(xenkbd_cleanup);
+
+MODULE_LICENSE("GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/gntdev/Makefile
---- linux-2.6.18.8/drivers/xen/gntdev/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/gntdev/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1 @@
-+obj-$(CONFIG_XEN_GRANT_DEV) := gntdev.o
-diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/drivers/xen/gntdev/gntdev.c
---- linux-2.6.18.8/drivers/xen/gntdev/gntdev.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/gntdev/gntdev.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,980 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.3.0/drivers/xen/gntdev/gntdev.c
+--- linux-2.6.18.8/drivers/xen/gntdev/gntdev.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/gntdev/gntdev.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1074 @@
+/******************************************************************************
+ * gntdev.c
+ *
@@ -90761,7 +135885,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+
-+#define MAX_GRANTS 128
++#define MAX_GRANTS_LIMIT 1024
++#define DEFAULT_MAX_GRANTS 128
+
+/* A slot can be in one of three states:
+ *
@@ -90808,7 +135933,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+typedef struct gntdev_file_private_data {
+
+ /* Array of grant information. */
-+ gntdev_grant_info_t grants[MAX_GRANTS];
++ gntdev_grant_info_t *grants;
++ uint32_t grants_size;
+
+ /* Read/write semaphore used to protect the grants array. */
+ struct rw_semaphore grants_sem;
@@ -90820,7 +135946,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+ * been compressed. However, this is not visible across invocations of
+ * the device.
+ */
-+ int32_t free_list[MAX_GRANTS];
++ int32_t *free_list;
+
+ /* The number of free slots in the grants array. */
+ uint32_t free_list_size;
@@ -91032,7 +136158,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+
+ /* First search from the start_index to the end of the array. */
+ range_length = 0;
-+ for (i = start_index; i < MAX_GRANTS; ++i) {
++ for (i = start_index; i < private_data->grants_size; ++i) {
+ if (private_data->grants[i].state == GNTDEV_SLOT_INVALID) {
+ if (range_length == 0) {
+ range_start = i;
@@ -91061,6 +136187,47 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+ return -ENOMEM;
+}
+
++static int init_private_data(gntdev_file_private_data_t *priv,
++ uint32_t max_grants)
++{
++ int i;
++
++ /* Allocate space for the kernel-mapping of granted pages. */
++ priv->foreign_pages =
++ alloc_empty_pages_and_pagevec(max_grants);
++ if (!priv->foreign_pages)
++ goto nomem_out;
++
++ /* Allocate the grant list and free-list. */
++ priv->grants = kmalloc(max_grants * sizeof(gntdev_grant_info_t),
++ GFP_KERNEL);
++ if (!priv->grants)
++ goto nomem_out2;
++ priv->free_list = kmalloc(max_grants * sizeof(int32_t), GFP_KERNEL);
++ if (!priv->free_list)
++ goto nomem_out3;
++
++ /* Initialise the free-list, which contains all slots at first. */
++ for (i = 0; i < max_grants; ++i) {
++ priv->free_list[max_grants - i - 1] = i;
++ priv->grants[i].state = GNTDEV_SLOT_INVALID;
++ priv->grants[i].u.free_list_index = max_grants - i - 1;
++ }
++ priv->grants_size = max_grants;
++ priv->free_list_size = max_grants;
++ priv->next_fit_index = 0;
++
++ return 0;
++
++nomem_out3:
++ kfree(priv->grants);
++nomem_out2:
++ free_empty_pages_and_pagevec(priv->foreign_pages, max_grants);
++nomem_out:
++ return -ENOMEM;
++
++}
++
+/* Interface functions. */
+
+/* Initialises the driver. Called when the module is loaded. */
@@ -91118,7 +136285,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+static int gntdev_open(struct inode *inode, struct file *flip)
+{
+ gntdev_file_private_data_t *private_data;
-+ int i;
+
+ try_module_get(THIS_MODULE);
+
@@ -91127,21 +136293,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+ if (!private_data)
+ goto nomem_out;
+
-+ /* Allocate space for the kernel-mapping of granted pages. */
-+ private_data->foreign_pages =
-+ alloc_empty_pages_and_pagevec(MAX_GRANTS);
-+ if (!private_data->foreign_pages)
-+ goto nomem_out2;
-+
-+ /* Initialise the free-list, which contains all slots at first.
-+ */
-+ for (i = 0; i < MAX_GRANTS; ++i) {
-+ private_data->free_list[MAX_GRANTS - i - 1] = i;
-+ private_data->grants[i].state = GNTDEV_SLOT_INVALID;
-+ private_data->grants[i].u.free_list_index = MAX_GRANTS - i - 1;
-+ }
-+ private_data->free_list_size = MAX_GRANTS;
-+ private_data->next_fit_index = 0;
++ /* These will be lazily initialised by init_private_data. */
++ private_data->grants = NULL;
++ private_data->free_list = NULL;
++ private_data->foreign_pages = NULL;
+
+ init_rwsem(&private_data->grants_sem);
+ init_rwsem(&private_data->free_list_sem);
@@ -91150,8 +136305,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+
+ return 0;
+
-+nomem_out2:
-+ kfree(private_data);
+nomem_out:
+ return -ENOMEM;
+}
@@ -91163,10 +136316,14 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+ if (flip->private_data) {
+ gntdev_file_private_data_t *private_data =
+ (gntdev_file_private_data_t *) flip->private_data;
-+ if (private_data->foreign_pages) {
++ if (private_data->foreign_pages)
+ free_empty_pages_and_pagevec
-+ (private_data->foreign_pages, MAX_GRANTS);
-+ }
++ (private_data->foreign_pages,
++ private_data->grants_size);
++ if (private_data->grants)
++ kfree(private_data->grants);
++ if (private_data->free_list)
++ kfree(private_data->free_list);
+ kfree(private_data);
+ }
+ module_put(THIS_MODULE);
@@ -91197,7 +136354,17 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+ return -EINVAL;
+ }
+
-+ if (unlikely((size <= 0) || (size + slot_index) > MAX_GRANTS)) {
++ /* Test to make sure that the grants array has been initialised. */
++ down_read(&private_data->grants_sem);
++ if (unlikely(!private_data->grants)) {
++ up_read(&private_data->grants_sem);
++ printk(KERN_ERR "Attempted to mmap before ioctl.\n");
++ return -EINVAL;
++ }
++ up_read(&private_data->grants_sem);
++
++ if (unlikely((size <= 0) ||
++ (size + slot_index) > private_data->grants_size)) {
+ printk(KERN_ERR "Invalid number of pages or offset"
+ "(num_pages = %d, first_slot = %ld).\n",
+ size, slot_index);
@@ -91227,7 +136394,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+
+ /* The VM area contains pages from another VM. */
+ vma->vm_flags |= VM_FOREIGN;
-+ vma->vm_private_data = kzalloc(size * sizeof(struct page_struct *),
++ vma->vm_private_data = kzalloc(size * sizeof(struct page *),
+ GFP_KERNEL);
+ if (vma->vm_private_data == NULL) {
+ printk(KERN_ERR "Couldn't allocate mapping structure for VM "
@@ -91507,6 +136674,33 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+ gntdev_file_private_data_t *private_data =
+ (gntdev_file_private_data_t *) flip->private_data;
+
++ /* On the first invocation, we will lazily initialise the grant array
++ * and free-list.
++ */
++ if (unlikely(!private_data->grants)
++ && likely(cmd != IOCTL_GNTDEV_SET_MAX_GRANTS)) {
++ down_write(&private_data->grants_sem);
++
++ if (unlikely(private_data->grants)) {
++ up_write(&private_data->grants_sem);
++ goto private_data_initialised;
++ }
++
++ /* Just use the default. Setting to a non-default is handled
++ * in the ioctl switch.
++ */
++ rc = init_private_data(private_data, DEFAULT_MAX_GRANTS);
++
++ up_write(&private_data->grants_sem);
++
++ if (rc) {
++ printk (KERN_ERR "Initialising gntdev private data "
++ "failed.\n");
++ return rc;
++ }
++ }
++
++private_data_initialised:
+ switch (cmd) {
+ case IOCTL_GNTDEV_MAP_GRANT_REF:
+ {
@@ -91690,24 +136884,391 @@ diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/gntdev.c linux-2.6.18-xen-3.2.0/dri
+ get_offset_out:
+ return rc;
+ }
++ case IOCTL_GNTDEV_SET_MAX_GRANTS:
++ {
++ struct ioctl_gntdev_set_max_grants op;
++ if ((rc = copy_from_user(&op,
++ (void __user *) arg,
++ sizeof(op)))) {
++ rc = -EFAULT;
++ goto set_max_out;
++ }
++ down_write(&private_data->grants_sem);
++ if (private_data->grants) {
++ rc = -EBUSY;
++ goto set_max_unlock_out;
++ }
++ if (op.count > MAX_GRANTS_LIMIT) {
++ rc = -EINVAL;
++ goto set_max_unlock_out;
++ }
++ rc = init_private_data(private_data, op.count);
++ set_max_unlock_out:
++ up_write(&private_data->grants_sem);
++ set_max_out:
++ return rc;
++ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/netback/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/netback/Makefile
---- linux-2.6.18.8/drivers/xen/netback/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netback/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,5 @@
-+obj-$(CONFIG_XEN_NETDEV_BACKEND) := netbk.o
-+obj-$(CONFIG_XEN_NETDEV_LOOPBACK) += netloop.o
+diff -rpuN linux-2.6.18.8/drivers/xen/gntdev/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/gntdev/Makefile
+--- linux-2.6.18.8/drivers/xen/gntdev/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/gntdev/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1 @@
++obj-$(CONFIG_XEN_GRANT_DEV) := gntdev.o
+diff -rpuN linux-2.6.18.8/drivers/xen/Kconfig linux-2.6.18-xen-3.3.0/drivers/xen/Kconfig
+--- linux-2.6.18.8/drivers/xen/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,314 @@
++#
++# This Kconfig describe xen options
++#
+
-+netbk-y := netback.o xenbus.o interface.o accel.o
-+netloop-y := loopback.o
-diff -rpuN linux-2.6.18.8/drivers/xen/netback/accel.c linux-2.6.18-xen-3.2.0/drivers/xen/netback/accel.c
---- linux-2.6.18.8/drivers/xen/netback/accel.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netback/accel.c 2008-02-15 16:22:06.000000000 -0800
++mainmenu "Xen Configuration"
++
++config XEN
++ bool
++
++if XEN
++config XEN_INTERFACE_VERSION
++ hex
++ default 0x00030207
++
++menu "XEN"
++
++config XEN_PRIVILEGED_GUEST
++ bool "Privileged Guest (domain 0)"
++ help
++ Support for privileged operation (domain 0)
++
++config XEN_UNPRIVILEGED_GUEST
++ def_bool !XEN_PRIVILEGED_GUEST
++
++config XEN_PRIVCMD
++ def_bool y
++ depends on PROC_FS
++
++config XEN_XENBUS_DEV
++ def_bool y
++ depends on PROC_FS
++
++config XEN_NETDEV_ACCEL_SFC_UTIL
++ depends on X86
++ tristate
++
++config XEN_BACKEND
++ tristate "Backend driver support"
++ default XEN_PRIVILEGED_GUEST
++ help
++ Support for backend device drivers that provide I/O services
++ to other virtual machines.
++
++config XEN_BLKDEV_BACKEND
++ tristate "Block-device backend driver"
++ depends on XEN_BACKEND
++ default XEN_BACKEND
++ help
++ The block-device backend driver allows the kernel to export its
++ block devices to other guests via a high-performance shared-memory
++ interface.
++
++config XEN_BLKDEV_TAP
++ tristate "Block-device tap backend driver"
++ depends on XEN_BACKEND
++ default XEN_BACKEND
++ help
++ The block tap driver is an alternative to the block back driver
++ and allows VM block requests to be redirected to userspace through
++ a device interface. The tap allows user-space development of
++ high-performance block backends, where disk images may be implemented
++ as files, in memory, or on other hosts across the network. This
++ driver can safely coexist with the existing blockback driver.
++
++config XEN_NETDEV_BACKEND
++ tristate "Network-device backend driver"
++ depends on XEN_BACKEND && NET
++ default XEN_BACKEND
++ help
++ The network-device backend driver allows the kernel to export its
++ network devices to other guests via a high-performance shared-memory
++ interface.
++
++config XEN_NETDEV_PIPELINED_TRANSMITTER
++ bool "Pipelined transmitter (DANGEROUS)"
++ depends on XEN_NETDEV_BACKEND
++ help
++ If the net backend is a dumb domain, such as a transparent Ethernet
++ bridge with no local IP interface, it is safe to say Y here to get
++ slightly lower network overhead.
++ If the backend has a local IP interface; or may be doing smart things
++ like reassembling packets to perform firewall filtering; or if you
++ are unsure; or if you experience network hangs when this option is
++ enabled; then you must say N here.
++
++config XEN_NETDEV_ACCEL_SFC_BACKEND
++ tristate "Network-device backend driver acceleration for Solarflare NICs"
++ depends on XEN_NETDEV_BACKEND && SFC && SFC_RESOURCE && X86
++ select XEN_NETDEV_ACCEL_SFC_UTIL
++ default m
++
++config XEN_NETDEV_LOOPBACK
++ tristate "Network-device loopback driver"
++ depends on XEN_NETDEV_BACKEND
++ help
++ A two-interface loopback device to emulate a local netfront-netback
++ connection. If unsure, it is probably safe to say N here.
++
++config XEN_PCIDEV_BACKEND
++ tristate "PCI-device backend driver"
++ depends on PCI && XEN_BACKEND
++ default XEN_BACKEND
++ help
++ The PCI device backend driver allows the kernel to export arbitrary
++ PCI devices to other guests. If you select this to be a module, you
++ will need to make sure no other driver has bound to the device(s)
++ you want to make visible to other guests.
++
++choice
++ prompt "PCI Backend Mode"
++ depends on XEN_PCIDEV_BACKEND
++ default XEN_PCIDEV_BACKEND_VPCI if !IA64
++ default XEN_PCIDEV_BACKEND_CONTROLLER if IA64
++
++config XEN_PCIDEV_BACKEND_VPCI
++ bool "Virtual PCI"
++ ---help---
++ This PCI Backend hides the true PCI topology and makes the frontend
++ think there is a single PCI bus with only the exported devices on it.
++ For example, a device at 03:05.0 will be re-assigned to 00:00.0. A
++ second device at 02:1a.1 will be re-assigned to 00:01.1.
++
++config XEN_PCIDEV_BACKEND_PASS
++ bool "Passthrough"
++ ---help---
++ This PCI Backend provides a real view of the PCI topology to the
++ frontend (for example, a device at 06:01.b will still appear at
++ 06:01.b to the frontend). This is similar to how Xen 2.0.x exposed
++ PCI devices to its driver domains. This may be required for drivers
++ which depend on finding their hardward in certain bus/slot
++ locations.
++
++config XEN_PCIDEV_BACKEND_SLOT
++ bool "Slot"
++ ---help---
++ This PCI Backend hides the true PCI topology and makes the frontend
++ think there is a single PCI bus with only the exported devices on it.
++ Contrary to the virtual PCI backend, a function becomes a new slot.
++ For example, a device at 03:05.2 will be re-assigned to 00:00.0. A
++ second device at 02:1a.1 will be re-assigned to 00:01.0.
++
++config XEN_PCIDEV_BACKEND_CONTROLLER
++ bool "Controller"
++ depends on IA64
++ ---help---
++ This PCI backend virtualizes the PCI bus topology by providing a
++ virtual bus per PCI root device. Devices which are physically under
++ the same root bus will appear on the same virtual bus. For systems
++ with complex I/O addressing, this is the only backend which supports
++ extended I/O port spaces and MMIO translation offsets. This backend
++ also supports slot virtualization. For example, a device at
++ 0000:01:02.1 will be re-assigned to 0000:00:00.0. A second device
++ at 0000:02:05.0 (behind a P2P bridge on bus 0000:01) will be
++ re-assigned to 0000:00:01.0. A third device at 0000:16:05.0 (under
++ a different PCI root bus) will be re-assigned to 0000:01:00.0.
++
++endchoice
++
++config XEN_PCIDEV_BE_DEBUG
++ bool "PCI Backend Debugging"
++ depends on XEN_PCIDEV_BACKEND
++
++config XEN_TPMDEV_BACKEND
++ tristate "TPM-device backend driver"
++ depends on XEN_BACKEND
++ help
++ The TPM-device backend driver
++
++config XEN_SCSI_BACKEND
++ tristate "SCSI backend driver"
++ depends on SCSI && XEN_BACKEND
++ default m
++ help
++ The SCSI backend driver allows the kernel to export its SCSI Devices
++ to other guests via a high-performance shared-memory interface.
++
++config XEN_BLKDEV_FRONTEND
++ tristate "Block-device frontend driver"
++ default y
++ help
++ The block-device frontend driver allows the kernel to access block
++ devices mounted within another guest OS. Unless you are building a
++ dedicated device-driver domain, or your master control domain
++ (domain 0), then you almost certainly want to say Y here.
++
++config XEN_NETDEV_FRONTEND
++ tristate "Network-device frontend driver"
++ depends on NET
++ default y
++ help
++ The network-device frontend driver allows the kernel to access
++ network interfaces within another guest OS. Unless you are building a
++ dedicated device-driver domain, or your master control domain
++ (domain 0), then you almost certainly want to say Y here.
++
++config XEN_NETDEV_ACCEL_SFC_FRONTEND
++ tristate "Network-device frontend driver acceleration for Solarflare NICs"
++ depends on XEN_NETDEV_FRONTEND && X86
++ select XEN_NETDEV_ACCEL_SFC_UTIL
++ default m
++
++config XEN_SCSI_FRONTEND
++ tristate "SCSI frontend driver"
++ depends on SCSI
++ default m
++ help
++ The SCSI frontend driver allows the kernel to access SCSI Devices
++ within another guest OS.
++
++config XEN_GRANT_DEV
++ tristate "User-space granted page access driver"
++ default XEN_PRIVILEGED_GUEST
++ help
++ Device for accessing (in user-space) pages that have been granted
++ by other domains.
++
++config XEN_FRAMEBUFFER
++ tristate "Framebuffer-device frontend driver"
++ depends on FB
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++ default y
++ help
++ The framebuffer-device frontend drivers allows the kernel to create a
++ virtual framebuffer. This framebuffer can be viewed in another
++ domain. Unless this domain has access to a real video card, you
++ probably want to say Y here.
++
++config XEN_KEYBOARD
++ tristate "Keyboard-device frontend driver"
++ depends on XEN_FRAMEBUFFER && INPUT
++ default y
++ help
++ The keyboard-device frontend driver allows the kernel to create a
++ virtual keyboard. This keyboard can then be driven by another
++ domain. If you've said Y to CONFIG_XEN_FRAMEBUFFER, you probably
++ want to say Y here.
++
++config XEN_SCRUB_PAGES
++ bool "Scrub memory before freeing it to Xen"
++ default y
++ help
++ Erase memory contents before freeing it back to Xen's global
++ pool. This ensures that any secrets contained within that
++ memory (e.g., private keys) cannot be found by other guests that
++ may be running on the machine. Most people will want to say Y here.
++ If security is not a concern then you may increase performance by
++ saying N.
++
++config XEN_DISABLE_SERIAL
++ bool "Disable serial port drivers"
++ default y
++ help
++ Disable serial port drivers, allowing the Xen console driver
++ to provide a serial console at ttyS0.
++
++config XEN_SYSFS
++ tristate "Export Xen attributes in sysfs"
++ depends on SYSFS
++ select SYS_HYPERVISOR
++ default y
++ help
++ Xen hypervisor attributes will show up under /sys/hypervisor/.
++
++choice
++ prompt "Xen version compatibility"
++ default XEN_COMPAT_030002_AND_LATER
++
++ config XEN_COMPAT_030002_AND_LATER
++ bool "3.0.2 and later"
++
++ config XEN_COMPAT_030004_AND_LATER
++ bool "3.0.4 and later"
++
++ config XEN_COMPAT_030100_AND_LATER
++ bool "3.1.0 and later"
++
++ config XEN_COMPAT_LATEST_ONLY
++ bool "no compatibility code"
++
++endchoice
++
++config XEN_COMPAT
++ hex
++ default 0xffffff if XEN_COMPAT_LATEST_ONLY
++ default 0x030100 if XEN_COMPAT_030100_AND_LATER
++ default 0x030004 if XEN_COMPAT_030004_AND_LATER
++ default 0x030002 if XEN_COMPAT_030002_AND_LATER
++ default 0
++
++endmenu
++
++config HAVE_IRQ_IGNORE_UNHANDLED
++ def_bool y
++
++config NO_IDLE_HZ
++ def_bool y
++
++config XEN_SMPBOOT
++ def_bool y
++ depends on SMP && !PPC_XEN
++
++config XEN_BALLOON
++ def_bool y
++ depends on !PPC_XEN
++
++config XEN_XENCOMM
++ bool
++
++config XEN_DEVMEM
++ def_bool y
++
++endif
+diff -rpuN linux-2.6.18.8/drivers/xen/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/Makefile
+--- linux-2.6.18.8/drivers/xen/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,25 @@
++obj-y += core/
++obj-y += console/
++obj-y += evtchn/
++obj-y += xenbus/
++obj-y += char/
++
++obj-y += util.o
++obj-$(CONFIG_XEN_BALLOON) += balloon/
++obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
++obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/
++obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
++obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/
++obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/
++obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/
++obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback/
++obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront/
++obj-$(CONFIG_XEN_FRAMEBUFFER) += fbfront/
++obj-$(CONFIG_XEN_KEYBOARD) += fbfront/
++obj-$(CONFIG_XEN_SCSI_BACKEND) += scsiback/
++obj-$(CONFIG_XEN_SCSI_FRONTEND) += scsifront/
++obj-$(CONFIG_XEN_PRIVCMD) += privcmd/
++obj-$(CONFIG_XEN_GRANT_DEV) += gntdev/
++obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL) += sfc_netutil/
++obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND) += sfc_netfront/
++obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND) += sfc_netback/
+diff -rpuN linux-2.6.18.8/drivers/xen/netback/accel.c linux-2.6.18-xen-3.3.0/drivers/xen/netback/accel.c
+--- linux-2.6.18.8/drivers/xen/netback/accel.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netback/accel.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,269 @@
+/******************************************************************************
+ * drivers/xen/netback/accel.c
@@ -91978,9 +137539,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/accel.c linux-2.6.18-xen-3.2.0/dri
+{
+ INIT_LIST_HEAD(&accelerators_list);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/netback/common.h linux-2.6.18-xen-3.2.0/drivers/xen/netback/common.h
---- linux-2.6.18.8/drivers/xen/netback/common.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netback/common.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/netback/common.h linux-2.6.18-xen-3.3.0/drivers/xen/netback/common.h
+--- linux-2.6.18.8/drivers/xen/netback/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netback/common.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,217 @@
+/******************************************************************************
+ * arch/xen/drivers/netif/backend/common.h
@@ -92199,9 +137760,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/common.h linux-2.6.18-xen-3.2.0/dr
+}
+
+#endif /* __NETIF__BACKEND__COMMON_H__ */
-diff -rpuN linux-2.6.18.8/drivers/xen/netback/interface.c linux-2.6.18-xen-3.2.0/drivers/xen/netback/interface.c
---- linux-2.6.18.8/drivers/xen/netback/interface.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netback/interface.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/netback/interface.c linux-2.6.18-xen-3.3.0/drivers/xen/netback/interface.c
+--- linux-2.6.18.8/drivers/xen/netback/interface.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netback/interface.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,336 @@
+/******************************************************************************
+ * arch/xen/drivers/netif/backend/interface.c
@@ -92539,9 +138100,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/interface.c linux-2.6.18-xen-3.2.0
+
+ free_netdev(netif->dev);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/netback/loopback.c linux-2.6.18-xen-3.2.0/drivers/xen/netback/loopback.c
---- linux-2.6.18.8/drivers/xen/netback/loopback.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netback/loopback.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/netback/loopback.c linux-2.6.18-xen-3.3.0/drivers/xen/netback/loopback.c
+--- linux-2.6.18.8/drivers/xen/netback/loopback.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netback/loopback.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,324 @@
+/******************************************************************************
+ * netback/loopback.c
@@ -92867,9 +138428,18 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/loopback.c linux-2.6.18-xen-3.2.0/
+module_exit(loopback_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/netback/netback.c linux-2.6.18-xen-3.2.0/drivers/xen/netback/netback.c
---- linux-2.6.18.8/drivers/xen/netback/netback.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netback/netback.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/netback/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/netback/Makefile
+--- linux-2.6.18.8/drivers/xen/netback/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netback/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_XEN_NETDEV_BACKEND) := netbk.o
++obj-$(CONFIG_XEN_NETDEV_LOOPBACK) += netloop.o
++
++netbk-y := netback.o xenbus.o interface.o accel.o
++netloop-y := loopback.o
+diff -rpuN linux-2.6.18.8/drivers/xen/netback/netback.c linux-2.6.18-xen-3.3.0/drivers/xen/netback/netback.c
+--- linux-2.6.18.8/drivers/xen/netback/netback.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netback/netback.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,1614 @@
+/******************************************************************************
+ * drivers/xen/netback/netback.c
@@ -94485,10 +140055,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/netback.c linux-2.6.18-xen-3.2.0/d
+module_init(netback_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/netback/xenbus.c linux-2.6.18-xen-3.2.0/drivers/xen/netback/xenbus.c
---- linux-2.6.18.8/drivers/xen/netback/xenbus.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netback/xenbus.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,452 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/netback/xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/netback/xenbus.c
+--- linux-2.6.18.8/drivers/xen/netback/xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netback/xenbus.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,454 @@
+/* Xenbus code for netif backend
+ Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+ Copyright (C) 2005 XenSource Ltd
@@ -94531,6 +140101,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ netback_remove_accelerators(be, dev);
+
+ if (be->netif) {
++ kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+ netif_disconnect(be->netif);
+ be->netif = NULL;
+ }
@@ -94722,6 +140293,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ break;
+
+ case XenbusStateConnected:
++ if (dev->state == XenbusStateConnected)
++ break;
+ backend_create_netif(be);
+ if (be->netif)
+ connect(be);
@@ -94729,6 +140302,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+
+ case XenbusStateClosing:
+ if (be->netif) {
++ kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+ netif_disconnect(be->netif);
+ be->netif = NULL;
+ }
@@ -94741,8 +140315,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ break;
+ /* fall through if not online */
+ case XenbusStateUnknown:
-+ if (be->netif != NULL)
-+ kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+ device_unregister(&dev->dev);
+ break;
+
@@ -94920,7 +140492,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+/* ** Driver Registration ** */
+
+
-+static struct xenbus_device_id netback_ids[] = {
++static const struct xenbus_device_id netback_ids[] = {
+ { "vif" },
+ { "" }
+};
@@ -94941,18 +140513,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+{
+ xenbus_register_backend(&netback);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/netfront/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/netfront/Makefile
---- linux-2.6.18.8/drivers/xen/netfront/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netfront/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,4 @@
-+
-+obj-$(CONFIG_XEN_NETDEV_FRONTEND) := xennet.o
-+
-+xennet-objs := netfront.o accel.o
-diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/drivers/xen/netfront/accel.c
---- linux-2.6.18.8/drivers/xen/netfront/accel.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netfront/accel.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,815 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.3.0/drivers/xen/netfront/accel.c
+--- linux-2.6.18.8/drivers/xen/netfront/accel.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netfront/accel.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,824 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ *
@@ -94987,7 +140551,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/dr
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
-+
++#include <asm/hypervisor.h>
+#include <xen/xenbus.h>
+
+#include "netfront.h"
@@ -95015,6 +140579,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/dr
+/* Lock to protect access to accelerators_list */
+static spinlock_t accelerators_lock;
+
++/* Workqueue to process acceleration configuration changes */
++struct workqueue_struct *accel_watch_workqueue;
++
+/* Mutex to prevent concurrent loads and suspends, etc. */
+DEFINE_MUTEX(accelerator_mutex);
+
@@ -95022,6 +140589,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/dr
+{
+ INIT_LIST_HEAD(&accelerators_list);
+ spin_lock_init(&accelerators_lock);
++
++ accel_watch_workqueue = create_workqueue("net_accel");
+}
+
+void netif_exit_accel(void)
@@ -95029,6 +140598,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/dr
+ struct netfront_accelerator *accelerator, *tmp;
+ unsigned long flags;
+
++ flush_workqueue(accel_watch_workqueue);
++ destroy_workqueue(accel_watch_workqueue);
++
+ spin_lock_irqsave(&accelerators_lock, flags);
+
+ list_for_each_entry_safe(accelerator, tmp, &accelerators_list, link) {
@@ -95111,7 +140683,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/dr
+ struct netfront_accel_vif_state *vif_state =
+ container_of(watch, struct netfront_accel_vif_state,
+ accel_watch);
-+ schedule_work(&vif_state->accel_work);
++ queue_work(accel_watch_workqueue, &vif_state->accel_work);
+}
+
+
@@ -95146,7 +140718,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/dr
+ kfree(vif_state->accel_watch.node);
+ vif_state->accel_watch.node = NULL;
+
-+ flush_scheduled_work();
++ flush_workqueue(accel_watch_workqueue);
+
+ /* Clean up any state left from watch */
+ if (vif_state->accel_frontend != NULL) {
@@ -95656,8 +141228,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/dr
+ * accelerator, so no need to call accelerator_probe_new_vif()
+ * directly here
+ */
-+ netfront_accelerator_add_watch(np);
-+ return 0;
++ if (dev->state == XenbusStateConnected)
++ netfront_accelerator_add_watch(np);
++ return 0;
+}
+
+
@@ -95768,10 +141341,18 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/accel.c linux-2.6.18-xen-3.2.0/dr
+ return rc;
+}
+
-diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0/drivers/xen/netfront/netfront.c
---- linux-2.6.18.8/drivers/xen/netfront/netfront.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netfront/netfront.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,2222 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/netfront/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/netfront/Makefile
+--- linux-2.6.18.8/drivers/xen/netfront/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netfront/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,4 @@
++
++obj-$(CONFIG_XEN_NETDEV_FRONTEND) := xennet.o
++
++xennet-objs := netfront.o accel.o
+diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.3.0/drivers/xen/netfront/netfront.c
+--- linux-2.6.18.8/drivers/xen/netfront/netfront.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netfront/netfront.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2240 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ *
@@ -95837,7 +141418,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+#include <asm/uaccess.h>
+#include <xen/interface/grant_table.h>
+#include <xen/gnttab.h>
-+#include <xen/hypercall.h>
+
+struct netfront_cb {
+ struct page *page;
@@ -96141,10 +141721,14 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ struct xenbus_transaction xbt;
+ int err;
+
-+ err = xen_net_read_mac(dev, info->mac);
-+ if (err) {
-+ xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
-+ goto out;
++ /* Read mac only in the first setup. */
++ if (!is_valid_ether_addr(info->mac)) {
++ err = xen_net_read_mac(dev, info->mac);
++ if (err) {
++ xenbus_dev_fatal(dev, err, "parsing %s/mac",
++ dev->nodename);
++ goto out;
++ }
+ }
+
+ /* Create shared ring, alloc event channel. */
@@ -96249,7 +141833,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ info->tx.sring = NULL;
+ info->irq = 0;
+
-+ txs = (struct netif_tx_sring *)get_zeroed_page(GFP_KERNEL|__GFP_HIGH);
++ txs = (struct netif_tx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
+ if (!txs) {
+ err = -ENOMEM;
+ xenbus_dev_fatal(dev, err, "allocating tx ring page");
@@ -96265,7 +141849,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ }
+ info->tx_ring_ref = err;
+
-+ rxs = (struct netif_rx_sring *)get_zeroed_page(GFP_KERNEL|__GFP_HIGH);
++ rxs = (struct netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
+ if (!rxs) {
+ err = -ENOMEM;
+ xenbus_dev_fatal(dev, err, "allocating rx ring page");
@@ -96311,6 +141895,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ case XenbusStateInitialising:
+ case XenbusStateInitialised:
+ case XenbusStateConnected:
++ case XenbusStateReconfiguring:
++ case XenbusStateReconfigured:
+ case XenbusStateUnknown:
+ case XenbusStateClosed:
+ break;
@@ -96620,8 +142206,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ /* Check return status of HYPERVISOR_memory_op(). */
+ if (unlikely(np->rx_mcl[i].result != i))
+ panic("Unable to reduce memory reservation\n");
-+ while (i--)
-+ BUG_ON(np->rx_mcl[i].result);
++ while (nr_flips--)
++ BUG_ON(np->rx_mcl[nr_flips].result);
+ } else {
+ if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+ &reservation) != i)
@@ -96800,6 +142386,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+
+ np->stats.tx_bytes += skb->len;
+ np->stats.tx_packets++;
++ dev->trans_start = jiffies;
+
+ /* Note: It is not safe to access skb after network_tx_buf_gc()! */
+ network_tx_buf_gc(dev);
@@ -96832,6 +142419,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ netfront_accelerator_call_stop_napi_irq(np, dev);
+
+ netif_rx_schedule(dev);
++ dev->last_rx = jiffies;
+ }
+ }
+
@@ -97434,7 +143022,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ np->grant_rx_ref[i] = GRANT_INVALID_REF;
+ add_id_to_freelist(np->rx_skbs, i);
+
-+ skb_shinfo(skb)->nr_frags = 0;
+ dev_kfree_skb(skb);
+ }
+
@@ -97461,6 +143048,23 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ return &np->stats;
+}
+
++static int xennet_set_mac_address(struct net_device *dev, void *p)
++{
++ struct netfront_info *np = netdev_priv(dev);
++ struct sockaddr *addr = p;
++
++ if (netif_running(dev))
++ return -EBUSY;
++
++ if (!is_valid_ether_addr(addr->sa_data))
++ return -EADDRNOTAVAIL;
++
++ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++ memcpy(np->mac, addr->sa_data, ETH_ALEN);
++
++ return 0;
++}
++
+static int xennet_change_mtu(struct net_device *dev, int mtu)
+{
+ int max = xennet_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
@@ -97848,6 +143452,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ netdev->poll = netif_poll;
+ netdev->set_multicast_list = network_set_multicast_list;
+ netdev->uninit = netif_uninit;
++ netdev->set_mac_address = xennet_set_mac_address;
+ netdev->change_mtu = xennet_change_mtu;
+ netdev->weight = 64;
+ netdev->features = NETIF_F_IP_CSUM;
@@ -97927,14 +143532,14 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+/* ** Driver registration ** */
+
+
-+static struct xenbus_device_id netfront_ids[] = {
++static const struct xenbus_device_id netfront_ids[] = {
+ { "vif" },
+ { "" }
+};
+MODULE_ALIAS("xen:vif");
+
+
-+static struct xenbus_driver netfront = {
++static struct xenbus_driver netfront_driver = {
+ .name = "vif",
+ .owner = THIS_MODULE,
+ .ids = netfront_ids,
@@ -97962,9 +143567,6 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ MODPARM_rx_flip = 1; /* Default is to flip. */
+#endif
+
-+ if (is_initial_xendomain())
-+ return 0;
-+
+ netif_init_accel();
+
+ IPRINTK("Initialising virtual ethernet driver.\n");
@@ -97973,30 +143575,27 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.c linux-2.6.18-xen-3.2.0
+ (void)register_inetaddr_notifier(&notifier_inetdev);
+#endif
+
-+ return xenbus_register_frontend(&netfront);
++ return xenbus_register_frontend(&netfront_driver);
+}
+module_init(netif_init);
+
+
+static void __exit netif_exit(void)
+{
-+ if (is_initial_xendomain())
-+ return;
-+
+#ifdef CONFIG_INET
+ unregister_inetaddr_notifier(&notifier_inetdev);
+#endif
+
+ netif_exit_accel();
+
-+ return xenbus_unregister_driver(&netfront);
++ return xenbus_unregister_driver(&netfront_driver);
+}
+module_exit(netif_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.h linux-2.6.18-xen-3.2.0/drivers/xen/netfront/netfront.h
---- linux-2.6.18.8/drivers/xen/netfront/netfront.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/netfront/netfront.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.h linux-2.6.18-xen-3.3.0/drivers/xen/netfront/netfront.h
+--- linux-2.6.18.8/drivers/xen/netfront/netfront.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/netfront/netfront.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,274 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
@@ -98272,29 +143871,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/netfront/netfront.h linux-2.6.18-xen-3.2.0
+void init_accelerator_vif(struct netfront_info *np,
+ struct xenbus_device *dev);
+#endif /* NETFRONT_H */
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/pciback/Makefile
---- linux-2.6.18.8/drivers/xen/pciback/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,16 @@
-+obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback.o
-+
-+pciback-y := pci_stub.o pciback_ops.o xenbus.o
-+pciback-y += conf_space.o conf_space_header.o \
-+ conf_space_capability.o \
-+ conf_space_capability_vpd.o \
-+ conf_space_capability_pm.o \
-+ conf_space_quirks.o
-+pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
-+pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT) += slot.o
-+pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
-+pciback-$(CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER) += controller.o
-+
-+ifeq ($(CONFIG_XEN_PCIDEV_BE_DEBUG),y)
-+EXTRA_CFLAGS += -DDEBUG
-+endif
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space.c
---- linux-2.6.18.8/drivers/xen/pciback/conf_space.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space.c
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,426 @@
+/*
+ * PCI Backend - Functions for creating a virtual configuration space for
@@ -98722,139 +144301,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space.c linux-2.6.18-xen-3.2.
+{
+ return pciback_config_capability_init();
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space.h linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space.h
---- linux-2.6.18.8/drivers/xen/pciback/conf_space.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space.h 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,126 @@
-+/*
-+ * PCI Backend - Common data structures for overriding the configuration space
-+ *
-+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
-+ */
-+
-+#ifndef __XEN_PCIBACK_CONF_SPACE_H__
-+#define __XEN_PCIBACK_CONF_SPACE_H__
-+
-+#include <linux/list.h>
-+#include <linux/err.h>
-+
-+/* conf_field_init can return an errno in a ptr with ERR_PTR() */
-+typedef void *(*conf_field_init) (struct pci_dev * dev, int offset);
-+typedef void (*conf_field_reset) (struct pci_dev * dev, int offset, void *data);
-+typedef void (*conf_field_free) (struct pci_dev * dev, int offset, void *data);
-+
-+typedef int (*conf_dword_write) (struct pci_dev * dev, int offset, u32 value,
-+ void *data);
-+typedef int (*conf_word_write) (struct pci_dev * dev, int offset, u16 value,
-+ void *data);
-+typedef int (*conf_byte_write) (struct pci_dev * dev, int offset, u8 value,
-+ void *data);
-+typedef int (*conf_dword_read) (struct pci_dev * dev, int offset, u32 * value,
-+ void *data);
-+typedef int (*conf_word_read) (struct pci_dev * dev, int offset, u16 * value,
-+ void *data);
-+typedef int (*conf_byte_read) (struct pci_dev * dev, int offset, u8 * value,
-+ void *data);
-+
-+/* These are the fields within the configuration space which we
-+ * are interested in intercepting reads/writes to and changing their
-+ * values.
-+ */
-+struct config_field {
-+ unsigned int offset;
-+ unsigned int size;
-+ unsigned int mask;
-+ conf_field_init init;
-+ conf_field_reset reset;
-+ conf_field_free release;
-+ void (*clean) (struct config_field * field);
-+ union {
-+ struct {
-+ conf_dword_write write;
-+ conf_dword_read read;
-+ } dw;
-+ struct {
-+ conf_word_write write;
-+ conf_word_read read;
-+ } w;
-+ struct {
-+ conf_byte_write write;
-+ conf_byte_read read;
-+ } b;
-+ } u;
-+ struct list_head list;
-+};
-+
-+struct config_field_entry {
-+ struct list_head list;
-+ struct config_field *field;
-+ unsigned int base_offset;
-+ void *data;
-+};
-+
-+#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
-+
-+/* Add fields to a device - the add_fields macro expects to get a pointer to
-+ * the first entry in an array (of which the ending is marked by size==0)
-+ */
-+int pciback_config_add_field_offset(struct pci_dev *dev,
-+ struct config_field *field,
-+ unsigned int offset);
-+
-+static inline int pciback_config_add_field(struct pci_dev *dev,
-+ struct config_field *field)
-+{
-+ return pciback_config_add_field_offset(dev, field, 0);
-+}
-+
-+static inline int pciback_config_add_fields(struct pci_dev *dev,
-+ struct config_field *field)
-+{
-+ int i, err = 0;
-+ for (i = 0; field[i].size != 0; i++) {
-+ err = pciback_config_add_field(dev, &field[i]);
-+ if (err)
-+ break;
-+ }
-+ return err;
-+}
-+
-+static inline int pciback_config_add_fields_offset(struct pci_dev *dev,
-+ struct config_field *field,
-+ unsigned int offset)
-+{
-+ int i, err = 0;
-+ for (i = 0; field[i].size != 0; i++) {
-+ err = pciback_config_add_field_offset(dev, &field[i], offset);
-+ if (err)
-+ break;
-+ }
-+ return err;
-+}
-+
-+/* Read/Write the real configuration space */
-+int pciback_read_config_byte(struct pci_dev *dev, int offset, u8 * value,
-+ void *data);
-+int pciback_read_config_word(struct pci_dev *dev, int offset, u16 * value,
-+ void *data);
-+int pciback_read_config_dword(struct pci_dev *dev, int offset, u32 * value,
-+ void *data);
-+int pciback_write_config_byte(struct pci_dev *dev, int offset, u8 value,
-+ void *data);
-+int pciback_write_config_word(struct pci_dev *dev, int offset, u16 value,
-+ void *data);
-+int pciback_write_config_dword(struct pci_dev *dev, int offset, u32 value,
-+ void *data);
-+
-+int pciback_config_capability_init(void);
-+
-+int pciback_config_header_add_fields(struct pci_dev *dev);
-+int pciback_config_capability_add_fields(struct pci_dev *dev);
-+
-+#endif /* __XEN_PCIBACK_CONF_SPACE_H__ */
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_capability.c
---- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_capability.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability.c
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,71 @@
+/*
+ * PCI Backend - Handles the virtual fields found on the capability lists
@@ -98927,9 +144376,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.c linux-2.6.
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.h linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_capability.h
---- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_capability.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.h linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability.h
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,23 @@
+/*
+ * PCI Backend - Data structures for special overlays for structures on
@@ -98954,9 +144403,82 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability.h linux-2.6.
+};
+
+#endif
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_pm.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_capability_pm.c
---- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_pm.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_capability_pm.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_msi.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability_msi.c
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_msi.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability_msi.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,69 @@
++/*
++ * PCI Backend -- Configuration overlay for MSI capability
++ */
++#include <linux/pci.h>
++#include "conf_space.h"
++#include "conf_space_capability.h"
++#include <xen/interface/io/pciif.h>
++#include "pciback.h"
++
++int pciback_enable_msi(struct pciback_device *pdev,
++ struct pci_dev *dev, struct xen_pci_op *op)
++{
++ int otherend = pdev->xdev->otherend_id;
++ int status;
++
++ status = pci_enable_msi(dev);
++
++ if (status) {
++ printk("error enable msi for guest %x status %x\n", otherend, status);
++ op->value = 0;
++ return XEN_PCI_ERR_op_failed;
++ }
++
++ op->value = dev->irq;
++ return 0;
++}
++
++int pciback_disable_msi(struct pciback_device *pdev,
++ struct pci_dev *dev, struct xen_pci_op *op)
++{
++ pci_disable_msi(dev);
++
++ op->value = dev->irq;
++ return 0;
++}
++
++int pciback_enable_msix(struct pciback_device *pdev,
++ struct pci_dev *dev, struct xen_pci_op *op)
++{
++ int result;
++
++ if (op->value > SH_INFO_MAX_VEC)
++ return -EINVAL;
++ else {
++ struct msix_entry entries[op->value];
++ int i;
++
++ for (i = 0; i < op->value; i++) {
++ entries[i].entry = op->msix_entries[i].entry;
++ entries[i].vector = op->msix_entries[i].vector;
++ }
++
++ result = pci_enable_msix(dev, entries, op->value);
++ op->value = result;
++ }
++
++ return result;
++}
++
++int pciback_disable_msix(struct pciback_device *pdev,
++ struct pci_dev *dev, struct xen_pci_op *op)
++{
++
++ pci_disable_msix(dev);
++
++ op->value = dev->irq;
++ return 0;
++}
++
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_pm.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability_pm.c
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_pm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability_pm.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,128 @@
+/*
+ * PCI Backend - Configuration space overlay for power management
@@ -99086,9 +144608,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_pm.c linux-2
+ .capability = PCI_CAP_ID_PM,
+ .fields = caplist_pm,
+};
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_vpd.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_capability_vpd.c
---- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_vpd.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_capability_vpd.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_vpd.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability_vpd.c
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_vpd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_capability_vpd.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,42 @@
+/*
+ * PCI Backend - Configuration space overlay for Vital Product Data
@@ -99132,9 +144654,139 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_capability_vpd.c linux-
+ .capability = PCI_CAP_ID_VPD,
+ .fields = caplist_vpd,
+};
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_header.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_header.c
---- linux-2.6.18.8/drivers/xen/pciback/conf_space_header.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_header.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space.h linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space.h
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,126 @@
++/*
++ * PCI Backend - Common data structures for overriding the configuration space
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#ifndef __XEN_PCIBACK_CONF_SPACE_H__
++#define __XEN_PCIBACK_CONF_SPACE_H__
++
++#include <linux/list.h>
++#include <linux/err.h>
++
++/* conf_field_init can return an errno in a ptr with ERR_PTR() */
++typedef void *(*conf_field_init) (struct pci_dev * dev, int offset);
++typedef void (*conf_field_reset) (struct pci_dev * dev, int offset, void *data);
++typedef void (*conf_field_free) (struct pci_dev * dev, int offset, void *data);
++
++typedef int (*conf_dword_write) (struct pci_dev * dev, int offset, u32 value,
++ void *data);
++typedef int (*conf_word_write) (struct pci_dev * dev, int offset, u16 value,
++ void *data);
++typedef int (*conf_byte_write) (struct pci_dev * dev, int offset, u8 value,
++ void *data);
++typedef int (*conf_dword_read) (struct pci_dev * dev, int offset, u32 * value,
++ void *data);
++typedef int (*conf_word_read) (struct pci_dev * dev, int offset, u16 * value,
++ void *data);
++typedef int (*conf_byte_read) (struct pci_dev * dev, int offset, u8 * value,
++ void *data);
++
++/* These are the fields within the configuration space which we
++ * are interested in intercepting reads/writes to and changing their
++ * values.
++ */
++struct config_field {
++ unsigned int offset;
++ unsigned int size;
++ unsigned int mask;
++ conf_field_init init;
++ conf_field_reset reset;
++ conf_field_free release;
++ void (*clean) (struct config_field * field);
++ union {
++ struct {
++ conf_dword_write write;
++ conf_dword_read read;
++ } dw;
++ struct {
++ conf_word_write write;
++ conf_word_read read;
++ } w;
++ struct {
++ conf_byte_write write;
++ conf_byte_read read;
++ } b;
++ } u;
++ struct list_head list;
++};
++
++struct config_field_entry {
++ struct list_head list;
++ struct config_field *field;
++ unsigned int base_offset;
++ void *data;
++};
++
++#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
++
++/* Add fields to a device - the add_fields macro expects to get a pointer to
++ * the first entry in an array (of which the ending is marked by size==0)
++ */
++int pciback_config_add_field_offset(struct pci_dev *dev,
++ struct config_field *field,
++ unsigned int offset);
++
++static inline int pciback_config_add_field(struct pci_dev *dev,
++ struct config_field *field)
++{
++ return pciback_config_add_field_offset(dev, field, 0);
++}
++
++static inline int pciback_config_add_fields(struct pci_dev *dev,
++ struct config_field *field)
++{
++ int i, err = 0;
++ for (i = 0; field[i].size != 0; i++) {
++ err = pciback_config_add_field(dev, &field[i]);
++ if (err)
++ break;
++ }
++ return err;
++}
++
++static inline int pciback_config_add_fields_offset(struct pci_dev *dev,
++ struct config_field *field,
++ unsigned int offset)
++{
++ int i, err = 0;
++ for (i = 0; field[i].size != 0; i++) {
++ err = pciback_config_add_field_offset(dev, &field[i], offset);
++ if (err)
++ break;
++ }
++ return err;
++}
++
++/* Read/Write the real configuration space */
++int pciback_read_config_byte(struct pci_dev *dev, int offset, u8 * value,
++ void *data);
++int pciback_read_config_word(struct pci_dev *dev, int offset, u16 * value,
++ void *data);
++int pciback_read_config_dword(struct pci_dev *dev, int offset, u32 * value,
++ void *data);
++int pciback_write_config_byte(struct pci_dev *dev, int offset, u8 value,
++ void *data);
++int pciback_write_config_word(struct pci_dev *dev, int offset, u16 value,
++ void *data);
++int pciback_write_config_dword(struct pci_dev *dev, int offset, u32 value,
++ void *data);
++
++int pciback_config_capability_init(void);
++
++int pciback_config_header_add_fields(struct pci_dev *dev);
++int pciback_config_capability_add_fields(struct pci_dev *dev);
++
++#endif /* __XEN_PCIBACK_CONF_SPACE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_header.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_header.c
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space_header.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_header.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,323 @@
+/*
+ * PCI Backend - Handles the virtual fields in the configuration space headers.
@@ -99459,9 +145111,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_header.c linux-2.6.18-x
+ out:
+ return err;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_quirks.c
---- linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_quirks.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_quirks.c
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_quirks.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,126 @@
+/*
+ * PCI Backend - Handle special overlays for broken devices.
@@ -99589,9 +145241,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.c linux-2.6.18-x
+ out:
+ return ret;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.h linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_quirks.h
---- linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/conf_space_quirks.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.h linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_quirks.h
+--- linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/conf_space_quirks.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,35 @@
+/*
+ * PCI Backend - Data structures for special overlays for broken devices.
@@ -99628,10 +145280,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/conf_space_quirks.h linux-2.6.18-x
+int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg);
+
+#endif
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/controller.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/controller.c
---- linux-2.6.18.8/drivers/xen/pciback/controller.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/controller.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,404 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/controller.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/controller.c
+--- linux-2.6.18.8/drivers/xen/pciback/controller.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/controller.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ * Alex Williamson <alex.williamson@hp.com>
@@ -99725,7 +145377,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/controller.c linux-2.6.18-xen-3.2.
+ return dev;
+}
+
-+int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
++ int devid, publish_pci_dev_cb publish_cb)
+{
+ struct controller_dev_data *dev_data = pdev->pci_dev_data;
+ struct controller_dev_entry *dev_entry;
@@ -99799,6 +145452,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/controller.c linux-2.6.18-xen-3.2.
+
+out:
+ spin_unlock_irqrestore(&dev_data->lock, flags);
++
++ /* TODO: Publish virtual domain:bus:slot.func here. */
++
+ return ret;
+}
+
@@ -100036,10 +145692,31 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/controller.c linux-2.6.18-xen-3.2.
+ kfree(dev_data);
+ pdev->pci_dev_data = NULL;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/passthrough.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/passthrough.c
---- linux-2.6.18.8/drivers/xen/pciback/passthrough.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/passthrough.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,157 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/pciback/Makefile
+--- linux-2.6.18.8/drivers/xen/pciback/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,17 @@
++obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback.o
++
++pciback-y := pci_stub.o pciback_ops.o xenbus.o
++pciback-y += conf_space.o conf_space_header.o \
++ conf_space_capability.o \
++ conf_space_capability_vpd.o \
++ conf_space_capability_pm.o \
++ conf_space_quirks.o
++pciback-$(CONFIG_PCI_MSI) += conf_space_capability_msi.o
++pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
++pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT) += slot.o
++pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
++pciback-$(CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER) += controller.o
++
++ifeq ($(CONFIG_XEN_PCIDEV_BE_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/passthrough.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/passthrough.c
+--- linux-2.6.18.8/drivers/xen/pciback/passthrough.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/passthrough.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,166 @@
+/*
+ * PCI Backend - Provides restricted access to the real PCI bus topology
+ * to the frontend
@@ -100083,11 +145760,14 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/passthrough.c linux-2.6.18-xen-3.2
+ return dev;
+}
+
-+int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
++ int devid, publish_pci_dev_cb publish_cb)
+{
+ struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+ struct pci_dev_entry *dev_entry;
+ unsigned long flags;
++ unsigned int domain, bus, devfn;
++ int err;
+
+ dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
+ if (!dev_entry)
@@ -100098,7 +145778,13 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/passthrough.c linux-2.6.18-xen-3.2
+ list_add_tail(&dev_entry->list, &dev_data->dev_list);
+ spin_unlock_irqrestore(&dev_data->lock, flags);
+
-+ return 0;
++ /* Publish this device. */
++ domain = (unsigned int)pci_domain_nr(dev->bus);
++ bus = (unsigned int)dev->bus->number;
++ devfn = dev->devfn;
++ err = publish_cb(pdev, domain, bus, devfn, devid);
++
++ return err;
+}
+
+void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
@@ -100197,10 +145883,246 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/passthrough.c linux-2.6.18-xen-3.2
+ kfree(dev_data);
+ pdev->pci_dev_data = NULL;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pci_stub.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/pci_stub.c
---- linux-2.6.18.8/drivers/xen/pciback/pci_stub.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/pci_stub.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,929 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pciback.h linux-2.6.18-xen-3.3.0/drivers/xen/pciback/pciback.h
+--- linux-2.6.18.8/drivers/xen/pciback/pciback.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/pciback.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,111 @@
++/*
++ * PCI Backend Common Data Structures & Function Declarations
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#ifndef __XEN_PCIBACK_H__
++#define __XEN_PCIBACK_H__
++
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <xen/xenbus.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/workqueue.h>
++#include <asm/atomic.h>
++#include <xen/interface/io/pciif.h>
++
++struct pci_dev_entry {
++ struct list_head list;
++ struct pci_dev *dev;
++};
++
++#define _PDEVF_op_active (0)
++#define PDEVF_op_active (1<<(_PDEVF_op_active))
++
++struct pciback_device {
++ void *pci_dev_data;
++ spinlock_t dev_lock;
++
++ struct xenbus_device *xdev;
++
++ struct xenbus_watch be_watch;
++ u8 be_watching;
++
++ int evtchn_irq;
++
++ struct vm_struct *sh_area;
++ struct xen_pci_sharedinfo *sh_info;
++
++ unsigned long flags;
++
++ struct work_struct op_work;
++};
++
++struct pciback_dev_data {
++ struct list_head config_fields;
++ int permissive;
++ int warned_on_write;
++};
++
++/* Get/Put PCI Devices that are hidden from the PCI Backend Domain */
++struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev,
++ int domain, int bus,
++ int slot, int func);
++struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
++ struct pci_dev *dev);
++void pcistub_put_pci_dev(struct pci_dev *dev);
++
++/* Ensure a device is turned off or reset */
++void pciback_reset_device(struct pci_dev *pdev);
++
++/* Access a virtual configuration space for a PCI device */
++int pciback_config_init(void);
++int pciback_config_init_dev(struct pci_dev *dev);
++void pciback_config_free_dyn_fields(struct pci_dev *dev);
++void pciback_config_reset_dev(struct pci_dev *dev);
++void pciback_config_free_dev(struct pci_dev *dev);
++int pciback_config_read(struct pci_dev *dev, int offset, int size,
++ u32 * ret_val);
++int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value);
++
++/* Handle requests for specific devices from the frontend */
++typedef int (*publish_pci_dev_cb) (struct pciback_device *pdev,
++ unsigned int domain, unsigned int bus,
++ unsigned int devfn, unsigned int devid);
++typedef int (*publish_pci_root_cb) (struct pciback_device * pdev,
++ unsigned int domain, unsigned int bus);
++int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
++ int devid, publish_pci_dev_cb publish_cb);
++void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev);
++struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
++ unsigned int domain, unsigned int bus,
++ unsigned int devfn);
++int pciback_init_devices(struct pciback_device *pdev);
++int pciback_publish_pci_roots(struct pciback_device *pdev,
++ publish_pci_root_cb cb);
++void pciback_release_devices(struct pciback_device *pdev);
++
++/* Handles events from front-end */
++irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs);
++void pciback_do_op(void *data);
++
++int pciback_xenbus_register(void);
++void pciback_xenbus_unregister(void);
++
++#ifdef CONFIG_PCI_MSI
++int pciback_enable_msi(struct pciback_device *pdev,
++ struct pci_dev *dev, struct xen_pci_op *op);
++
++int pciback_disable_msi(struct pciback_device *pdev,
++ struct pci_dev *dev, struct xen_pci_op *op);
++
++
++int pciback_enable_msix(struct pciback_device *pdev,
++ struct pci_dev *dev, struct xen_pci_op *op);
++
++int pciback_disable_msix(struct pciback_device *pdev,
++ struct pci_dev *dev, struct xen_pci_op *op);
++#endif
++extern int verbose_request;
++#endif
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pciback_ops.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/pciback_ops.c
+--- linux-2.6.18.8/drivers/xen/pciback/pciback_ops.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/pciback_ops.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,117 @@
++/*
++ * PCI Backend Operations - respond to PCI requests from Frontend
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#include <linux/module.h>
++#include <asm/bitops.h>
++#include <xen/evtchn.h>
++#include "pciback.h"
++
++int verbose_request = 0;
++module_param(verbose_request, int, 0644);
++
++/* Ensure a device is "turned off" and ready to be exported.
++ * (Also see pciback_config_reset to ensure virtual configuration space is
++ * ready to be re-exported)
++ */
++void pciback_reset_device(struct pci_dev *dev)
++{
++ u16 cmd;
++
++ /* Disable devices (but not bridges) */
++ if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
++ pci_disable_device(dev);
++
++ pci_write_config_word(dev, PCI_COMMAND, 0);
++
++ dev->is_enabled = 0;
++ dev->is_busmaster = 0;
++ } else {
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ if (cmd & (PCI_COMMAND_INVALIDATE)) {
++ cmd &= ~(PCI_COMMAND_INVALIDATE);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++ dev->is_busmaster = 0;
++ }
++ }
++}
++
++static inline void test_and_schedule_op(struct pciback_device *pdev)
++{
++ /* Check that frontend is requesting an operation and that we are not
++ * already processing a request */
++ if (test_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)
++ && !test_and_set_bit(_PDEVF_op_active, &pdev->flags))
++ schedule_work(&pdev->op_work);
++}
++
++/* Performing the configuration space reads/writes must not be done in atomic
++ * context because some of the pci_* functions can sleep (mostly due to ACPI
++ * use of semaphores). This function is intended to be called from a work
++ * queue in process context taking a struct pciback_device as a parameter */
++void pciback_do_op(void *data)
++{
++ struct pciback_device *pdev = data;
++ struct pci_dev *dev;
++ struct xen_pci_op *op = &pdev->sh_info->op;
++
++ dev = pciback_get_pci_dev(pdev, op->domain, op->bus, op->devfn);
++
++ if (dev == NULL)
++ op->err = XEN_PCI_ERR_dev_not_found;
++ else
++ {
++ switch (op->cmd)
++ {
++ case XEN_PCI_OP_conf_read:
++ op->err = pciback_config_read(dev,
++ op->offset, op->size, &op->value);
++ break;
++ case XEN_PCI_OP_conf_write:
++ op->err = pciback_config_write(dev,
++ op->offset, op->size, op->value);
++ break;
++#ifdef CONFIG_PCI_MSI
++ case XEN_PCI_OP_enable_msi:
++ op->err = pciback_enable_msi(pdev, dev, op);
++ break;
++ case XEN_PCI_OP_disable_msi:
++ op->err = pciback_disable_msi(pdev, dev, op);
++ break;
++ case XEN_PCI_OP_enable_msix:
++ op->err = pciback_enable_msix(pdev, dev, op);
++ break;
++ case XEN_PCI_OP_disable_msix:
++ op->err = pciback_disable_msix(pdev, dev, op);
++ break;
++#endif
++ default:
++ op->err = XEN_PCI_ERR_not_implemented;
++ break;
++ }
++ }
++ /* Tell the driver domain that we're done. */
++ wmb();
++ clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
++ notify_remote_via_irq(pdev->evtchn_irq);
++
++ /* Mark that we're done. */
++ smp_mb__before_clear_bit(); /* /after/ clearing PCIF_active */
++ clear_bit(_PDEVF_op_active, &pdev->flags);
++ smp_mb__after_clear_bit(); /* /before/ final check for work */
++
++ /* Check to see if the driver domain tried to start another request in
++ * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active. */
++ test_and_schedule_op(pdev);
++}
++
++irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct pciback_device *pdev = dev_id;
++
++ test_and_schedule_op(pdev);
++
++ return IRQ_HANDLED;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pci_stub.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/pci_stub.c
+--- linux-2.6.18.8/drivers/xen/pciback/pci_stub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/pci_stub.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,948 @@
+/*
+ * PCI Stub Driver - Grabs devices in backend to be exported later
+ *
@@ -101008,6 +146930,22 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pci_stub.c linux-2.6.18-xen-3.2.0/
+
+DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
+
++#ifdef CONFIG_PCI_MSI
++
++int pciback_get_owner(struct pci_dev *dev)
++{
++ struct pcistub_device *psdev;
++
++ psdev = pcistub_device_find(pci_domain_nr(dev->bus), dev->bus->number,
++ PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
++
++ if (!psdev || !psdev->pdev)
++ return -1;
++
++ return psdev->pdev->xdev->otherend_id;
++}
++#endif
++
+static void pcistub_exit(void)
+{
+ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_new_slot);
@@ -101018,6 +146956,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pci_stub.c linux-2.6.18-xen-3.2.0/
+ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);
+
+ pci_unregister_driver(&pciback_pci_driver);
++ WARN_ON(unregister_msi_get_owner(pciback_get_owner));
+}
+
+static int __init pcistub_init(void)
@@ -101075,6 +147014,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pci_stub.c linux-2.6.18-xen-3.2.0/
+ err = driver_create_file(&pciback_pci_driver.driver,
+ &driver_attr_permissive);
+
++ if (!err)
++ err = register_msi_get_owner(pciback_get_owner);
+ if (err)
+ pcistub_exit();
+
@@ -101130,206 +147071,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pci_stub.c linux-2.6.18-xen-3.2.0/
+module_exit(pciback_cleanup);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pciback.h linux-2.6.18-xen-3.2.0/drivers/xen/pciback/pciback.h
---- linux-2.6.18.8/drivers/xen/pciback/pciback.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/pciback.h 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,93 @@
-+/*
-+ * PCI Backend Common Data Structures & Function Declarations
-+ *
-+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
-+ */
-+#ifndef __XEN_PCIBACK_H__
-+#define __XEN_PCIBACK_H__
-+
-+#include <linux/pci.h>
-+#include <linux/interrupt.h>
-+#include <xen/xenbus.h>
-+#include <linux/list.h>
-+#include <linux/spinlock.h>
-+#include <linux/workqueue.h>
-+#include <asm/atomic.h>
-+#include <xen/interface/io/pciif.h>
-+
-+struct pci_dev_entry {
-+ struct list_head list;
-+ struct pci_dev *dev;
-+};
-+
-+#define _PDEVF_op_active (0)
-+#define PDEVF_op_active (1<<(_PDEVF_op_active))
-+
-+struct pciback_device {
-+ void *pci_dev_data;
-+ spinlock_t dev_lock;
-+
-+ struct xenbus_device *xdev;
-+
-+ struct xenbus_watch be_watch;
-+ u8 be_watching;
-+
-+ int evtchn_irq;
-+
-+ struct vm_struct *sh_area;
-+ struct xen_pci_sharedinfo *sh_info;
-+
-+ unsigned long flags;
-+
-+ struct work_struct op_work;
-+};
-+
-+struct pciback_dev_data {
-+ struct list_head config_fields;
-+ int permissive;
-+ int warned_on_write;
-+};
-+
-+/* Get/Put PCI Devices that are hidden from the PCI Backend Domain */
-+struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev,
-+ int domain, int bus,
-+ int slot, int func);
-+struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
-+ struct pci_dev *dev);
-+void pcistub_put_pci_dev(struct pci_dev *dev);
-+
-+/* Ensure a device is turned off or reset */
-+void pciback_reset_device(struct pci_dev *pdev);
-+
-+/* Access a virtual configuration space for a PCI device */
-+int pciback_config_init(void);
-+int pciback_config_init_dev(struct pci_dev *dev);
-+void pciback_config_free_dyn_fields(struct pci_dev *dev);
-+void pciback_config_reset_dev(struct pci_dev *dev);
-+void pciback_config_free_dev(struct pci_dev *dev);
-+int pciback_config_read(struct pci_dev *dev, int offset, int size,
-+ u32 * ret_val);
-+int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value);
-+
-+/* Handle requests for specific devices from the frontend */
-+typedef int (*publish_pci_root_cb) (struct pciback_device * pdev,
-+ unsigned int domain, unsigned int bus);
-+int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev);
-+void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev);
-+struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
-+ unsigned int domain, unsigned int bus,
-+ unsigned int devfn);
-+int pciback_init_devices(struct pciback_device *pdev);
-+int pciback_publish_pci_roots(struct pciback_device *pdev,
-+ publish_pci_root_cb cb);
-+void pciback_release_devices(struct pciback_device *pdev);
-+
-+/* Handles events from front-end */
-+irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs);
-+void pciback_do_op(void *data);
-+
-+int pciback_xenbus_register(void);
-+void pciback_xenbus_unregister(void);
-+
-+extern int verbose_request;
-+#endif
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/pciback_ops.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/pciback_ops.c
---- linux-2.6.18.8/drivers/xen/pciback/pciback_ops.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/pciback_ops.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,95 @@
-+/*
-+ * PCI Backend Operations - respond to PCI requests from Frontend
-+ *
-+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
-+ */
-+#include <linux/module.h>
-+#include <asm/bitops.h>
-+#include <xen/evtchn.h>
-+#include "pciback.h"
-+
-+int verbose_request = 0;
-+module_param(verbose_request, int, 0644);
-+
-+/* Ensure a device is "turned off" and ready to be exported.
-+ * (Also see pciback_config_reset to ensure virtual configuration space is
-+ * ready to be re-exported)
-+ */
-+void pciback_reset_device(struct pci_dev *dev)
-+{
-+ u16 cmd;
-+
-+ /* Disable devices (but not bridges) */
-+ if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
-+ pci_disable_device(dev);
-+
-+ pci_write_config_word(dev, PCI_COMMAND, 0);
-+
-+ dev->is_enabled = 0;
-+ dev->is_busmaster = 0;
-+ } else {
-+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
-+ if (cmd & (PCI_COMMAND_INVALIDATE)) {
-+ cmd &= ~(PCI_COMMAND_INVALIDATE);
-+ pci_write_config_word(dev, PCI_COMMAND, cmd);
-+
-+ dev->is_busmaster = 0;
-+ }
-+ }
-+}
-+
-+static inline void test_and_schedule_op(struct pciback_device *pdev)
-+{
-+ /* Check that frontend is requesting an operation and that we are not
-+ * already processing a request */
-+ if (test_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)
-+ && !test_and_set_bit(_PDEVF_op_active, &pdev->flags))
-+ schedule_work(&pdev->op_work);
-+}
-+
-+/* Performing the configuration space reads/writes must not be done in atomic
-+ * context because some of the pci_* functions can sleep (mostly due to ACPI
-+ * use of semaphores). This function is intended to be called from a work
-+ * queue in process context taking a struct pciback_device as a parameter */
-+void pciback_do_op(void *data)
-+{
-+ struct pciback_device *pdev = data;
-+ struct pci_dev *dev;
-+ struct xen_pci_op *op = &pdev->sh_info->op;
-+
-+ dev = pciback_get_pci_dev(pdev, op->domain, op->bus, op->devfn);
-+
-+ if (dev == NULL)
-+ op->err = XEN_PCI_ERR_dev_not_found;
-+ else if (op->cmd == XEN_PCI_OP_conf_read)
-+ op->err = pciback_config_read(dev, op->offset, op->size,
-+ &op->value);
-+ else if (op->cmd == XEN_PCI_OP_conf_write)
-+ op->err = pciback_config_write(dev, op->offset, op->size,
-+ op->value);
-+ else
-+ op->err = XEN_PCI_ERR_not_implemented;
-+
-+ /* Tell the driver domain that we're done. */
-+ wmb();
-+ clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
-+ notify_remote_via_irq(pdev->evtchn_irq);
-+
-+ /* Mark that we're done. */
-+ smp_mb__before_clear_bit(); /* /after/ clearing PCIF_active */
-+ clear_bit(_PDEVF_op_active, &pdev->flags);
-+ smp_mb__after_clear_bit(); /* /before/ final check for work */
-+
-+ /* Check to see if the driver domain tried to start another request in
-+ * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active. */
-+ test_and_schedule_op(pdev);
-+}
-+
-+irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct pciback_device *pdev = dev_id;
-+
-+ test_and_schedule_op(pdev);
-+
-+ return IRQ_HANDLED;
-+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/slot.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/slot.c
---- linux-2.6.18.8/drivers/xen/pciback/slot.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/slot.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,151 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/slot.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/slot.c
+--- linux-2.6.18.8/drivers/xen/pciback/slot.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/slot.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,157 @@
+/*
+ * PCI Backend - Provides a Virtual PCI bus (with real devices)
+ * to the frontend
@@ -101376,7 +147121,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/slot.c linux-2.6.18-xen-3.2.0/driv
+ return dev;
+}
+
-+int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
++ int devid, publish_pci_dev_cb publish_cb)
+{
+ int err = 0, slot, bus;
+ struct slot_dev_data *slot_dev = pdev->pci_dev_data;
@@ -101409,6 +147155,11 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/slot.c linux-2.6.18-xen-3.2.0/driv
+
+ unlock:
+ spin_unlock_irqrestore(&slot_dev->lock, flags);
++
++ /* Publish this device. */
++ if(!err)
++ err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, 0), devid);
++
+ out:
+ return err;
+}
@@ -101481,10 +147232,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/slot.c linux-2.6.18-xen-3.2.0/driv
+ kfree(slot_dev);
+ pdev->pci_dev_data = NULL;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/vpci.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/vpci.c
---- linux-2.6.18.8/drivers/xen/pciback/vpci.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/vpci.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,204 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/vpci.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/vpci.c
+--- linux-2.6.18.8/drivers/xen/pciback/vpci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/vpci.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,212 @@
+/*
+ * PCI Backend - Provides a Virtual PCI bus (with real devices)
+ * to the frontend
@@ -101549,9 +147300,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/vpci.c linux-2.6.18-xen-3.2.0/driv
+ return 0;
+}
+
-+int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
++ int devid, publish_pci_dev_cb publish_cb)
+{
-+ int err = 0, slot;
++ int err = 0, slot, func;
+ struct pci_dev_entry *t, *dev_entry;
+ struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+ unsigned long flags;
@@ -101588,6 +147340,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/vpci.c linux-2.6.18-xen-3.2.0/driv
+ PCI_FUNC(dev->devfn));
+ list_add_tail(&dev_entry->list,
+ &vpci_dev->dev_list[slot]);
++ func = PCI_FUNC(dev->devfn);
+ goto unlock;
+ }
+ }
@@ -101601,6 +147354,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/vpci.c linux-2.6.18-xen-3.2.0/driv
+ pci_name(dev), slot);
+ list_add_tail(&dev_entry->list,
+ &vpci_dev->dev_list[slot]);
++ func = PCI_FUNC(dev->devfn);
+ goto unlock;
+ }
+ }
@@ -101611,6 +147365,11 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/vpci.c linux-2.6.18-xen-3.2.0/driv
+
+ unlock:
+ spin_unlock_irqrestore(&vpci_dev->lock, flags);
++
++ /* Publish this device. */
++ if(!err)
++ err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);
++
+ out:
+ return err;
+}
@@ -101689,10 +147448,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/vpci.c linux-2.6.18-xen-3.2.0/driv
+ kfree(vpci_dev);
+ pdev->pci_dev_data = NULL;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.2.0/drivers/xen/pciback/xenbus.c
---- linux-2.6.18.8/drivers/xen/pciback/xenbus.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pciback/xenbus.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,454 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/pciback/xenbus.c
+--- linux-2.6.18.8/drivers/xen/pciback/xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pciback/xenbus.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,704 @@
+/*
+ * PCI Backend Xenbus Setup - handles setup with frontend and xend
+ *
@@ -101737,22 +147496,35 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ return pdev;
+}
+
-+static void free_pdev(struct pciback_device *pdev)
++static void pciback_disconnect(struct pciback_device *pdev)
+{
-+ if (pdev->be_watching)
-+ unregister_xenbus_watch(&pdev->be_watch);
++ spin_lock(&pdev->dev_lock);
+
+ /* Ensure the guest can't trigger our handler before removing devices */
-+ if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ)
++ if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) {
+ unbind_from_irqhandler(pdev->evtchn_irq, pdev);
++ pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
++ }
+
+ /* If the driver domain started an op, make sure we complete it or
+ * delete it before releasing the shared memory */
+ cancel_delayed_work(&pdev->op_work);
+ flush_scheduled_work();
+
-+ if (pdev->sh_info)
++ if (pdev->sh_info != NULL) {
+ xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_area);
++ pdev->sh_info = NULL;
++ }
++
++ spin_unlock(&pdev->dev_lock);
++}
++
++static void free_pdev(struct pciback_device *pdev)
++{
++ if (pdev->be_watching)
++ unregister_xenbus_watch(&pdev->be_watch);
++
++ pciback_disconnect(pdev);
+
+ pciback_release_devices(pdev);
+
@@ -101856,31 +147628,87 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ return err;
+}
+
-+static void pciback_frontend_changed(struct xenbus_device *xdev,
-+ enum xenbus_state fe_state)
++static int pciback_publish_pci_dev(struct pciback_device *pdev,
++ unsigned int domain, unsigned int bus,
++ unsigned int devfn, unsigned int devid)
+{
-+ struct pciback_device *pdev = xdev->dev.driver_data;
++ int err;
++ int len;
++ char str[64];
+
-+ dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
++ len = snprintf(str, sizeof(str), "vdev-%d", devid);
++ if (unlikely(len >= (sizeof(str) - 1))) {
++ err = -ENOMEM;
++ goto out;
++ }
+
-+ switch (fe_state) {
-+ case XenbusStateInitialised:
-+ pciback_attach(pdev);
-+ break;
++ err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
++ "%04x:%02x:%02x.%02x", domain, bus,
++ PCI_SLOT(devfn), PCI_FUNC(devfn));
+
-+ case XenbusStateClosing:
-+ xenbus_switch_state(xdev, XenbusStateClosing);
-+ break;
++ out:
++ return err;
++}
+
-+ case XenbusStateUnknown:
-+ case XenbusStateClosed:
-+ dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
-+ device_unregister(&xdev->dev);
-+ break;
++static int pciback_export_device(struct pciback_device *pdev,
++ int domain, int bus, int slot, int func,
++ int devid)
++{
++ struct pci_dev *dev;
++ int err = 0;
+
-+ default:
-+ break;
++ dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n",
++ domain, bus, slot, func);
++
++ dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func);
++ if (!dev) {
++ err = -EINVAL;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Couldn't locate PCI device "
++ "(%04x:%02x:%02x.%01x)! "
++ "perhaps already in-use?",
++ domain, bus, slot, func);
++ goto out;
++ }
++
++ err = pciback_add_pci_dev(pdev, dev, devid, pciback_publish_pci_dev);
++ if (err)
++ goto out;
++
++ /* TODO: It'd be nice to export a bridge and have all of its children
++ * get exported with it. This may be best done in xend (which will
++ * have to calculate resource usage anyway) but we probably want to
++ * put something in here to ensure that if a bridge gets given to a
++ * driver domain, that all devices under that bridge are not given
++ * to other driver domains (as he who controls the bridge can disable
++ * it and stop the other devices from working).
++ */
++ out:
++ return err;
++}
++
++static int pciback_remove_device(struct pciback_device *pdev,
++ int domain, int bus, int slot, int func)
++{
++ int err = 0;
++ struct pci_dev *dev;
++
++ dev_dbg(&pdev->xdev->dev, "removing dom %x bus %x slot %x func %x\n",
++ domain, bus, slot, func);
++
++ dev = pciback_get_pci_dev(pdev, domain, bus, PCI_DEVFN(slot, func));
++ if (!dev) {
++ err = -EINVAL;
++ dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device "
++ "(%04x:%02x:%02x.%01x)! not owned by this domain\n",
++ domain, bus, slot, func);
++ goto out;
+ }
++
++ pciback_release_pci_dev(pdev, dev);
++
++ out:
++ return err;
+}
+
+static int pciback_publish_pci_root(struct pciback_device *pdev,
@@ -101943,40 +147771,203 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ return err;
+}
+
-+static int pciback_export_device(struct pciback_device *pdev,
-+ int domain, int bus, int slot, int func)
++static int pciback_reconfigure(struct pciback_device *pdev)
+{
-+ struct pci_dev *dev;
+ int err = 0;
++ int num_devs;
++ int domain, bus, slot, func;
++ int substate;
++ int i, len;
++ char state_str[64];
++ char dev_str[64];
+
-+ dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n",
-+ domain, bus, slot, func);
++ spin_lock(&pdev->dev_lock);
+
-+ dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func);
-+ if (!dev) {
-+ err = -EINVAL;
++ dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
++
++ /* Make sure we only reconfigure once */
++ if (xenbus_read_driver_state(pdev->xdev->nodename) !=
++ XenbusStateReconfiguring)
++ goto out;
++
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
++ &num_devs);
++ if (err != 1) {
++ if (err >= 0)
++ err = -EINVAL;
+ xenbus_dev_fatal(pdev->xdev, err,
-+ "Couldn't locate PCI device "
-+ "(%04x:%02x:%02x.%01x)! "
-+ "perhaps already in-use?",
-+ domain, bus, slot, func);
++ "Error reading number of devices");
+ goto out;
+ }
+
-+ err = pciback_add_pci_dev(pdev, dev);
-+ if (err)
-+ goto out;
++ for (i = 0; i < num_devs; i++) {
++ len = snprintf(state_str, sizeof(state_str), "state-%d", i);
++ if (unlikely(len >= (sizeof(state_str) - 1))) {
++ err = -ENOMEM;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "String overflow while reading "
++ "configuration");
++ goto out;
++ }
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, state_str,
++ "%d", &substate);
++ if (err != 1)
++ substate = XenbusStateUnknown;
+
-+ /* TODO: It'd be nice to export a bridge and have all of its children
-+ * get exported with it. This may be best done in xend (which will
-+ * have to calculate resource usage anyway) but we probably want to
-+ * put something in here to ensure that if a bridge gets given to a
-+ * driver domain, that all devices under that bridge are not given
-+ * to other driver domains (as he who controls the bridge can disable
-+ * it and stop the other devices from working).
-+ */
++ switch (substate) {
++ case XenbusStateInitialising:
++ dev_dbg(&pdev->xdev->dev, "Attaching dev-%d ...\n", i);
++
++ len = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
++ if (unlikely(len >= (sizeof(dev_str) - 1))) {
++ err = -ENOMEM;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "String overflow while "
++ "reading configuration");
++ goto out;
++ }
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
++ dev_str, "%x:%x:%x.%x",
++ &domain, &bus, &slot, &func);
++ if (err < 0) {
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error reading device "
++ "configuration");
++ goto out;
++ }
++ if (err != 4) {
++ err = -EINVAL;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error parsing pci device "
++ "configuration");
++ goto out;
++ }
++
++ err = pciback_export_device(pdev, domain, bus, slot,
++ func, i);
++ if (err)
++ goto out;
++
++ /* Publish pci roots. */
++ err = pciback_publish_pci_roots(pdev, pciback_publish_pci_root);
++ if (err) {
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error while publish PCI root"
++ "buses for frontend");
++ goto out;
++ }
++
++ err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
++ state_str, "%d",
++ XenbusStateInitialised);
++ if (err) {
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error switching substate of "
++ "dev-%d\n", i);
++ goto out;
++ }
++ break;
++
++ case XenbusStateClosing:
++ dev_dbg(&pdev->xdev->dev, "Detaching dev-%d ...\n", i);
++
++ len = snprintf(dev_str, sizeof(dev_str), "vdev-%d", i);
++ if (unlikely(len >= (sizeof(dev_str) - 1))) {
++ err = -ENOMEM;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "String overflow while "
++ "reading configuration");
++ goto out;
++ }
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
++ dev_str, "%x:%x:%x.%x",
++ &domain, &bus, &slot, &func);
++ if (err < 0) {
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error reading device "
++ "configuration");
++ goto out;
++ }
++ if (err != 4) {
++ err = -EINVAL;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error parsing pci device "
++ "configuration");
++ goto out;
++ }
++
++ err = pciback_remove_device(pdev, domain, bus, slot,
++ func);
++ if(err)
++ goto out;
++
++ /* TODO: If at some point we implement support for pci
++ * root hot-remove on pcifront side, we'll need to
++ * remove unnecessary xenstore nodes of pci roots here.
++ */
++
++ break;
++
++ default:
++ break;
++ }
++ }
++
++ err = xenbus_switch_state(pdev->xdev, XenbusStateReconfigured);
++ if (err) {
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error switching to reconfigured state!");
++ goto out;
++ }
++
+ out:
-+ return err;
++ spin_unlock(&pdev->dev_lock);
++
++ return 0;
++}
++
++static void pciback_frontend_changed(struct xenbus_device *xdev,
++ enum xenbus_state fe_state)
++{
++ struct pciback_device *pdev = xdev->dev.driver_data;
++
++ dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
++
++ switch (fe_state) {
++ case XenbusStateInitialised:
++ pciback_attach(pdev);
++ break;
++
++ case XenbusStateReconfiguring:
++ pciback_reconfigure(pdev);
++ break;
++
++ case XenbusStateConnected:
++ /* pcifront switched its state from reconfiguring to connected.
++ * Then switch to connected state.
++ */
++ xenbus_switch_state(xdev, XenbusStateConnected);
++ break;
++
++ case XenbusStateClosing:
++ pciback_disconnect(pdev);
++ xenbus_switch_state(xdev, XenbusStateClosing);
++ break;
++
++ case XenbusStateClosed:
++ pciback_disconnect(pdev);
++ xenbus_switch_state(xdev, XenbusStateClosed);
++ if (xenbus_dev_is_online(xdev))
++ break;
++ /* fall through if not online */
++ case XenbusStateUnknown:
++ dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
++ device_unregister(&xdev->dev);
++ break;
++
++ default:
++ break;
++ }
+}
+
+static int pciback_setup_backend(struct pciback_device *pdev)
@@ -101986,6 +147977,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ int err = 0;
+ int i, num_devs;
+ char dev_str[64];
++ char state_str[64];
+
+ spin_lock(&pdev->dev_lock);
+
@@ -102033,9 +148025,26 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ goto out;
+ }
+
-+ err = pciback_export_device(pdev, domain, bus, slot, func);
++ err = pciback_export_device(pdev, domain, bus, slot, func, i);
+ if (err)
+ goto out;
++
++ /* Switch substate of this device. */
++ l = snprintf(state_str, sizeof(state_str), "state-%d", i);
++ if (unlikely(l >= (sizeof(state_str) - 1))) {
++ err = -ENOMEM;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "String overflow while reading "
++ "configuration");
++ goto out;
++ }
++ err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, state_str,
++ "%d", XenbusStateInitialised);
++ if (err) {
++ xenbus_dev_fatal(pdev->xdev, err, "Error switching "
++ "substate of dev-%d\n", i);
++ goto out;
++ }
+ }
+
+ err = pciback_publish_pci_roots(pdev, pciback_publish_pci_root);
@@ -102121,7 +148130,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+ return 0;
+}
+
-+static struct xenbus_device_id xenpci_ids[] = {
++static const struct xenbus_device_id xenpci_ids[] = {
+ {"pci"},
+ {{0}},
+};
@@ -102147,9 +148156,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pciback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+{
+ xenbus_unregister_driver(&xenbus_pciback_driver);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/Makefile
---- linux-2.6.18.8/drivers/xen/pcifront/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/Makefile 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/Makefile
+--- linux-2.6.18.8/drivers/xen/pcifront/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,7 @@
+obj-y += pcifront.o
+
@@ -102158,9 +148167,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/Makefile linux-2.6.18-xen-3.2.0/d
+ifeq ($(CONFIG_XEN_PCIDEV_FE_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
-diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci.c linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/pci.c
---- linux-2.6.18.8/drivers/xen/pcifront/pci.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/pci.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci.c linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/pci.c
+--- linux-2.6.18.8/drivers/xen/pcifront/pci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/pci.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ * PCI Frontend Operations - ensure only one PCI frontend runs at a time
@@ -102208,10 +148217,56 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci.c linux-2.6.18-xen-3.2.0/driv
+
+ spin_unlock(&pcifront_dev_lock);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci_op.c linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/pci_op.c
---- linux-2.6.18.8/drivers/xen/pcifront/pci_op.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/pci_op.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,386 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pcifront.h linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/pcifront.h
+--- linux-2.6.18.8/drivers/xen/pcifront/pcifront.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/pcifront.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,42 @@
++/*
++ * PCI Frontend - Common data structures & function declarations
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#ifndef __XEN_PCIFRONT_H__
++#define __XEN_PCIFRONT_H__
++
++#include <linux/spinlock.h>
++#include <linux/pci.h>
++#include <xen/xenbus.h>
++#include <xen/interface/io/pciif.h>
++#include <xen/pcifront.h>
++
++struct pci_bus_entry {
++ struct list_head list;
++ struct pci_bus *bus;
++};
++
++struct pcifront_device {
++ struct xenbus_device *xdev;
++ struct list_head root_buses;
++ spinlock_t dev_lock;
++
++ int evtchn;
++ int gnt_ref;
++
++ /* Lock this when doing any operations in sh_info */
++ spinlock_t sh_info_lock;
++ struct xen_pci_sharedinfo *sh_info;
++};
++
++int pcifront_connect(struct pcifront_device *pdev);
++void pcifront_disconnect(struct pcifront_device *pdev);
++
++int pcifront_scan_root(struct pcifront_device *pdev,
++ unsigned int domain, unsigned int bus);
++int pcifront_rescan_root(struct pcifront_device *pdev,
++ unsigned int domain, unsigned int bus);
++void pcifront_free_roots(struct pcifront_device *pdev);
++
++#endif /* __XEN_PCIFRONT_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci_op.c linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/pci_op.c
+--- linux-2.6.18.8/drivers/xen/pcifront/pci_op.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/pci_op.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,551 @@
+/*
+ * PCI Frontend Operations - Communicates with frontend
+ *
@@ -102491,6 +148546,122 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci_op.c linux-2.6.18-xen-3.2.0/d
+ .write = pcifront_bus_write,
+};
+
++#ifdef CONFIG_PCI_MSI
++int pci_frontend_enable_msix(struct pci_dev *dev,
++ struct msix_entry *entries,
++ int nvec)
++{
++ int err;
++ int i;
++ struct xen_pci_op op = {
++ .cmd = XEN_PCI_OP_enable_msix,
++ .domain = pci_domain_nr(dev->bus),
++ .bus = dev->bus->number,
++ .devfn = dev->devfn,
++ .value = nvec,
++ };
++ struct pcifront_sd *sd = dev->bus->sysdata;
++ struct pcifront_device *pdev = pcifront_get_pdev(sd);
++
++ if (nvec > SH_INFO_MAX_VEC) {
++ printk("too much vector for pci frontend%x\n", nvec);
++ return -EINVAL;
++ }
++
++ for (i = 0; i < nvec; i++) {
++ op.msix_entries[i].entry = entries[i].entry;
++ op.msix_entries[i].vector = entries[i].vector;
++ }
++
++ err = do_pci_op(pdev, &op);
++
++ if (!err) {
++ if (!op.value) {
++ /* we get the result */
++ for ( i = 0; i < nvec; i++)
++ entries[i].vector = op.msix_entries[i].vector;
++ return 0;
++ }
++ else {
++ printk("enable msix get value %x\n", op.value);
++ return op.value;
++ }
++ }
++ else {
++ printk("enable msix get err %x\n", err);
++ return err;
++ }
++}
++
++void pci_frontend_disable_msix(struct pci_dev* dev)
++{
++ int err;
++ struct xen_pci_op op = {
++ .cmd = XEN_PCI_OP_disable_msix,
++ .domain = pci_domain_nr(dev->bus),
++ .bus = dev->bus->number,
++ .devfn = dev->devfn,
++ };
++ struct pcifront_sd *sd = dev->bus->sysdata;
++ struct pcifront_device *pdev = pcifront_get_pdev(sd);
++
++ err = do_pci_op(pdev, &op);
++
++ /* What should do for error ? */
++ if (err)
++ printk("pci_disable_msix get err %x\n", err);
++}
++
++int pci_frontend_enable_msi(struct pci_dev *dev)
++{
++ int err;
++ struct xen_pci_op op = {
++ .cmd = XEN_PCI_OP_enable_msi,
++ .domain = pci_domain_nr(dev->bus),
++ .bus = dev->bus->number,
++ .devfn = dev->devfn,
++ };
++ struct pcifront_sd *sd = dev->bus->sysdata;
++ struct pcifront_device *pdev = pcifront_get_pdev(sd);
++
++ err = do_pci_op(pdev, &op);
++ if (likely(!err)) {
++ dev->irq = op.value;
++ }
++ else {
++ printk("pci frontend enable msi failed for dev %x:%x \n",
++ op.bus, op.devfn);
++ err = -EINVAL;
++ }
++ return err;
++}
++
++void pci_frontend_disable_msi(struct pci_dev* dev)
++{
++ int err;
++ struct xen_pci_op op = {
++ .cmd = XEN_PCI_OP_disable_msi,
++ .domain = pci_domain_nr(dev->bus),
++ .bus = dev->bus->number,
++ .devfn = dev->devfn,
++ };
++ struct pcifront_sd *sd = dev->bus->sysdata;
++ struct pcifront_device *pdev = pcifront_get_pdev(sd);
++
++ err = do_pci_op(pdev, &op);
++ if (err == XEN_PCI_ERR_dev_not_found) {
++ /* XXX No response from backend, what shall we do? */
++ printk("get no response from backend for disable MSI\n");
++ return;
++ }
++ if (likely(!err))
++ dev->irq = op.value;
++ else
++ /* how can pciback notify us fail? */
++ printk("get fake response frombackend \n");
++}
++#endif /* CONFIG_PCI_MSI */
++
+/* Claim resources for the PCI frontend as-is, backend won't allow changes */
+static void pcifront_claim_resource(struct pci_dev *dev, void *data)
+{
@@ -102509,8 +148680,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci_op.c linux-2.6.18-xen-3.2.0/d
+ }
+}
+
-+int pcifront_scan_root(struct pcifront_device *pdev,
-+ unsigned int domain, unsigned int bus)
++int __devinit pcifront_scan_root(struct pcifront_device *pdev,
++ unsigned int domain, unsigned int bus)
+{
+ struct pci_bus *b;
+ struct pcifront_sd *sd = NULL;
@@ -102567,6 +148738,55 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci_op.c linux-2.6.18-xen-3.2.0/d
+ return err;
+}
+
++int __devinit pcifront_rescan_root(struct pcifront_device *pdev,
++ unsigned int domain, unsigned int bus)
++{
++ struct pci_bus *b;
++ struct pci_dev *d;
++ unsigned int devfn;
++
++#ifndef CONFIG_PCI_DOMAINS
++ if (domain != 0) {
++ dev_err(&pdev->xdev->dev,
++ "PCI Root in non-zero PCI Domain! domain=%d\n", domain);
++ dev_err(&pdev->xdev->dev,
++ "Please compile with CONFIG_PCI_DOMAINS\n");
++ return -EINVAL;
++ }
++#endif
++
++ dev_info(&pdev->xdev->dev, "Rescanning PCI Frontend Bus %04x:%02x\n",
++ domain, bus);
++
++ b = pci_find_bus(domain, bus);
++ if(!b)
++ /* If the bus is unknown, create it. */
++ return pcifront_scan_root(pdev, domain, bus);
++
++ /* Rescan the bus for newly attached functions and add.
++ * We omit handling of PCI bridge attachment because pciback prevents
++ * bridges from being exported.
++ */
++ for (devfn = 0; devfn < 0x100; devfn++) {
++ d = pci_get_slot(b, devfn);
++ if(d) {
++ /* Device is already known. */
++ pci_dev_put(d);
++ continue;
++ }
++
++ d = pci_scan_single_device(b, devfn);
++ if (d) {
++ dev_info(&pdev->xdev->dev, "New device on "
++ "%04x:%02x:%02x.%02x found.\n", domain, bus,
++ PCI_SLOT(devfn), PCI_FUNC(devfn));
++ pci_bus_add_device(d);
++ }
++ }
++
++ return 0;
++}
++
+static void free_root_bus_devs(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
@@ -102598,54 +148818,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pci_op.c linux-2.6.18-xen-3.2.0/d
+ kfree(bus_entry);
+ }
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/pcifront.h linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/pcifront.h
---- linux-2.6.18.8/drivers/xen/pcifront/pcifront.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/pcifront.h 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,40 @@
-+/*
-+ * PCI Frontend - Common data structures & function declarations
-+ *
-+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
-+ */
-+#ifndef __XEN_PCIFRONT_H__
-+#define __XEN_PCIFRONT_H__
-+
-+#include <linux/spinlock.h>
-+#include <linux/pci.h>
-+#include <xen/xenbus.h>
-+#include <xen/interface/io/pciif.h>
-+#include <xen/pcifront.h>
-+
-+struct pci_bus_entry {
-+ struct list_head list;
-+ struct pci_bus *bus;
-+};
-+
-+struct pcifront_device {
-+ struct xenbus_device *xdev;
-+ struct list_head root_buses;
-+ spinlock_t dev_lock;
-+
-+ int evtchn;
-+ int gnt_ref;
-+
-+ /* Lock this when doing any operations in sh_info */
-+ spinlock_t sh_info_lock;
-+ struct xen_pci_sharedinfo *sh_info;
-+};
-+
-+int pcifront_connect(struct pcifront_device *pdev);
-+void pcifront_disconnect(struct pcifront_device *pdev);
-+
-+int pcifront_scan_root(struct pcifront_device *pdev,
-+ unsigned int domain, unsigned int bus);
-+void pcifront_free_roots(struct pcifront_device *pdev);
-+
-+#endif /* __XEN_PCIFRONT_H__ */
-diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/xenbus.c linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/xenbus.c
---- linux-2.6.18.8/drivers/xen/pcifront/xenbus.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/pcifront/xenbus.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,296 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/xenbus.c
+--- linux-2.6.18.8/drivers/xen/pcifront/xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/pcifront/xenbus.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,455 @@
+/*
+ * PCI Frontend Xenbus Setup - handles setup with backend (imports page/evtchn)
+ *
@@ -102658,6 +148834,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/xenbus.c linux-2.6.18-xen-3.2.0/d
+#include <xen/gnttab.h>
+#include "pcifront.h"
+
++#ifndef __init_refok
++#define __init_refok
++#endif
++
+#define INVALID_GRANT_REF (0)
+#define INVALID_EVTCHN (-1)
+
@@ -102665,7 +148845,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/xenbus.c linux-2.6.18-xen-3.2.0/d
+{
+ struct pcifront_device *pdev;
+
-+ pdev = kmalloc(sizeof(struct pcifront_device), GFP_KERNEL);
++ pdev = kzalloc(sizeof(struct pcifront_device), GFP_KERNEL);
+ if (pdev == NULL)
+ goto out;
+
@@ -102771,7 +148951,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/xenbus.c linux-2.6.18-xen-3.2.0/d
+ return err;
+}
+
-+static int pcifront_try_connect(struct pcifront_device *pdev)
++static int __devinit pcifront_try_connect(struct pcifront_device *pdev)
+{
+ int err = -EFAULT;
+ int i, num_roots, len;
@@ -102851,41 +149031,196 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/xenbus.c linux-2.6.18-xen-3.2.0/d
+
+ prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
+
-+ if (prev_state < XenbusStateClosing)
-+ err = xenbus_switch_state(pdev->xdev, XenbusStateClosing);
++ if (prev_state >= XenbusStateClosing)
++ goto out;
+
-+ if (!err && prev_state == XenbusStateConnected)
++ if(prev_state == XenbusStateConnected) {
++ pcifront_free_roots(pdev);
+ pcifront_disconnect(pdev);
++ }
++
++ err = xenbus_switch_state(pdev->xdev, XenbusStateClosed);
+
++ out:
+ spin_unlock(&pdev->dev_lock);
+
+ return err;
+}
+
-+static void pcifront_backend_changed(struct xenbus_device *xdev,
-+ enum xenbus_state be_state)
++static int __devinit pcifront_attach_devices(struct pcifront_device *pdev)
++{
++ int err = -EFAULT;
++ int i, num_roots, len;
++ unsigned int domain, bus;
++ char str[64];
++
++ spin_lock(&pdev->dev_lock);
++
++ if (xenbus_read_driver_state(pdev->xdev->nodename) !=
++ XenbusStateReconfiguring)
++ goto out;
++
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
++ "root_num", "%d", &num_roots);
++ if (err == -ENOENT) {
++ xenbus_dev_error(pdev->xdev, err,
++ "No PCI Roots found, trying 0000:00");
++ err = pcifront_rescan_root(pdev, 0, 0);
++ num_roots = 0;
++ } else if (err != 1) {
++ if (err == 0)
++ err = -EINVAL;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error reading number of PCI roots");
++ goto out;
++ }
++
++ for (i = 0; i < num_roots; i++) {
++ len = snprintf(str, sizeof(str), "root-%d", i);
++ if (unlikely(len >= (sizeof(str) - 1))) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
++ "%x:%x", &domain, &bus);
++ if (err != 2) {
++ if (err >= 0)
++ err = -EINVAL;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error reading PCI root %d", i);
++ goto out;
++ }
++
++ err = pcifront_rescan_root(pdev, domain, bus);
++ if (err) {
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error scanning PCI root %04x:%02x",
++ domain, bus);
++ goto out;
++ }
++ }
++
++ xenbus_switch_state(pdev->xdev, XenbusStateConnected);
++
++ out:
++ spin_unlock(&pdev->dev_lock);
++ return err;
++}
++
++static int pcifront_detach_devices(struct pcifront_device *pdev)
++{
++ int err = 0;
++ int i, num_devs;
++ unsigned int domain, bus, slot, func;
++ struct pci_bus *pci_bus;
++ struct pci_dev *pci_dev;
++ char str[64];
++
++ spin_lock(&pdev->dev_lock);
++
++ if (xenbus_read_driver_state(pdev->xdev->nodename) !=
++ XenbusStateConnected)
++ goto out;
++
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, "num_devs", "%d",
++ &num_devs);
++ if (err != 1) {
++ if (err >= 0)
++ err = -EINVAL;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error reading number of PCI devices");
++ goto out;
++ }
++
++ /* Find devices being detached and remove them. */
++ for (i = 0; i < num_devs; i++) {
++ int l, state;
++ l = snprintf(str, sizeof(str), "state-%d", i);
++ if (unlikely(l >= (sizeof(str) - 1))) {
++ err = -ENOMEM;
++ goto out;
++ }
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, "%d",
++ &state);
++ if (err != 1)
++ state = XenbusStateUnknown;
++
++ if (state != XenbusStateClosing)
++ continue;
++
++ /* Remove device. */
++ l = snprintf(str, sizeof(str), "vdev-%d", i);
++ if (unlikely(l >= (sizeof(str) - 1))) {
++ err = -ENOMEM;
++ goto out;
++ }
++ err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
++ "%x:%x:%x.%x", &domain, &bus, &slot, &func);
++ if (err != 4) {
++ if (err >= 0)
++ err = -EINVAL;
++ xenbus_dev_fatal(pdev->xdev, err,
++ "Error reading PCI device %d", i);
++ goto out;
++ }
++
++ pci_bus = pci_find_bus(domain, bus);
++ if(!pci_bus) {
++ dev_dbg(&pdev->xdev->dev, "Cannot get bus %04x:%02x\n",
++ domain, bus);
++ continue;
++ }
++ pci_dev = pci_get_slot(pci_bus, PCI_DEVFN(slot, func));
++ if(!pci_dev) {
++ dev_dbg(&pdev->xdev->dev,
++ "Cannot get PCI device %04x:%02x:%02x.%02x\n",
++ domain, bus, slot, func);
++ continue;
++ }
++ pci_remove_bus_device(pci_dev);
++ pci_dev_put(pci_dev);
++
++ dev_dbg(&pdev->xdev->dev,
++ "PCI device %04x:%02x:%02x.%02x removed.\n",
++ domain, bus, slot, func);
++ }
++
++ err = xenbus_switch_state(pdev->xdev, XenbusStateReconfiguring);
++
++ out:
++ spin_unlock(&pdev->dev_lock);
++ return err;
++}
++
++static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
++ enum xenbus_state be_state)
+{
+ struct pcifront_device *pdev = xdev->dev.driver_data;
+
+ switch (be_state) {
-+ case XenbusStateClosing:
-+ dev_warn(&xdev->dev, "backend going away!\n");
-+ pcifront_try_disconnect(pdev);
-+ break;
-+
+ case XenbusStateUnknown:
++ case XenbusStateInitialising:
++ case XenbusStateInitWait:
++ case XenbusStateInitialised:
+ case XenbusStateClosed:
-+ dev_warn(&xdev->dev, "backend went away!\n");
-+ pcifront_try_disconnect(pdev);
-+
-+ device_unregister(&pdev->xdev->dev);
+ break;
+
+ case XenbusStateConnected:
+ pcifront_try_connect(pdev);
+ break;
+
-+ default:
++ case XenbusStateClosing:
++ dev_warn(&xdev->dev, "backend going away!\n");
++ pcifront_try_disconnect(pdev);
++ break;
++
++ case XenbusStateReconfiguring:
++ pcifront_detach_devices(pdev);
++ break;
++
++ case XenbusStateReconfigured:
++ pcifront_attach_devices(pdev);
+ break;
+ }
+}
@@ -102917,7 +149252,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/xenbus.c linux-2.6.18-xen-3.2.0/d
+ return 0;
+}
+
-+static struct xenbus_device_id xenpci_ids[] = {
++static const struct xenbus_device_id xenpci_ids[] = {
+ {"pci"},
+ {{0}},
+};
@@ -102942,16 +149277,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/pcifront/xenbus.c linux-2.6.18-xen-3.2.0/d
+
+/* Initialize after the Xen PCI Frontend Stub is initialized */
+subsys_initcall(pcifront_init);
-diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/privcmd/Makefile
---- linux-2.6.18.8/drivers/xen/privcmd/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/privcmd/Makefile 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,3 @@
-+
-+obj-y += privcmd.o
-+obj-$(CONFIG_COMPAT) += compat_privcmd.o
-diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/compat_privcmd.c linux-2.6.18-xen-3.2.0/drivers/xen/privcmd/compat_privcmd.c
---- linux-2.6.18.8/drivers/xen/privcmd/compat_privcmd.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/privcmd/compat_privcmd.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/compat_privcmd.c linux-2.6.18-xen-3.3.0/drivers/xen/privcmd/compat_privcmd.c
+--- linux-2.6.18.8/drivers/xen/privcmd/compat_privcmd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/privcmd/compat_privcmd.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,73 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -103026,10 +149354,17 @@ diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/compat_privcmd.c linux-2.6.18-xen-
+ }
+ return ret;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/privcmd.c linux-2.6.18-xen-3.2.0/drivers/xen/privcmd/privcmd.c
---- linux-2.6.18.8/drivers/xen/privcmd/privcmd.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/privcmd/privcmd.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,286 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/privcmd/Makefile
+--- linux-2.6.18.8/drivers/xen/privcmd/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/privcmd/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,3 @@
++
++obj-y += privcmd.o
++obj-$(CONFIG_COMPAT) += compat_privcmd.o
+diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/privcmd.c linux-2.6.18-xen-3.3.0/drivers/xen/privcmd/privcmd.c
+--- linux-2.6.18.8/drivers/xen/privcmd/privcmd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/privcmd/privcmd.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,356 @@
+/******************************************************************************
+ * privcmd.c
+ *
@@ -103125,13 +149460,16 @@ diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/privcmd.c linux-2.6.18-xen-3.2.0/d
+ break;
+
+ case IOCTL_PRIVCMD_MMAP: {
++#define MMAP_NR_PER_PAGE (int)((PAGE_SIZE-sizeof(struct list_head))/sizeof(privcmd_mmap_entry_t))
+ privcmd_mmap_t mmapcmd;
-+ privcmd_mmap_entry_t msg;
++ privcmd_mmap_entry_t *msg;
+ privcmd_mmap_entry_t __user *p;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+ unsigned long va;
+ int i, rc;
++ LIST_HEAD(pagelist);
++ struct list_head *l,*l2;
+
+ if (!is_initial_xendomain())
+ return -EPERM;
@@ -103140,63 +149478,92 @@ diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/privcmd.c linux-2.6.18-xen-3.2.0/d
+ return -EFAULT;
+
+ p = mmapcmd.entry;
-+ if (copy_from_user(&msg, p, sizeof(msg)))
-+ return -EFAULT;
++ for (i = 0; i < mmapcmd.num;) {
++ int nr = min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
++
++ rc = -ENOMEM;
++ l = (struct list_head *) __get_free_page(GFP_KERNEL);
++ if (l == NULL)
++ goto mmap_out;
++
++ INIT_LIST_HEAD(l);
++ list_add_tail(l, &pagelist);
++ msg = (privcmd_mmap_entry_t*)(l + 1);
++
++ rc = -EFAULT;
++ if (copy_from_user(msg, p, nr*sizeof(*msg)))
++ goto mmap_out;
++ i += nr;
++ p += nr;
++ }
++
++ l = pagelist.next;
++ msg = (privcmd_mmap_entry_t*)(l + 1);
+
+ down_write(&mm->mmap_sem);
+
-+ vma = find_vma(mm, msg.va);
++ vma = find_vma(mm, msg->va);
+ rc = -EINVAL;
-+ if (!vma || (msg.va != vma->vm_start) ||
++ if (!vma || (msg->va != vma->vm_start) ||
+ !privcmd_enforce_singleshot_mapping(vma))
+ goto mmap_out;
+
+ va = vma->vm_start;
+
-+ for (i = 0; i < mmapcmd.num; i++) {
-+ rc = -EFAULT;
-+ if (copy_from_user(&msg, p, sizeof(msg)))
-+ goto mmap_out;
-+
-+ /* Do not allow range to wrap the address space. */
-+ rc = -EINVAL;
-+ if ((msg.npages > (LONG_MAX >> PAGE_SHIFT)) ||
-+ ((unsigned long)(msg.npages << PAGE_SHIFT) >= -va))
-+ goto mmap_out;
++ i = 0;
++ list_for_each(l, &pagelist) {
++ int nr = i + min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
+
-+ /* Range chunks must be contiguous in va space. */
-+ if ((msg.va != va) ||
-+ ((msg.va+(msg.npages<<PAGE_SHIFT)) > vma->vm_end))
-+ goto mmap_out;
++ msg = (privcmd_mmap_entry_t*)(l + 1);
++ while (i<nr) {
+
-+ if ((rc = direct_remap_pfn_range(
-+ vma,
-+ msg.va & PAGE_MASK,
-+ msg.mfn,
-+ msg.npages << PAGE_SHIFT,
-+ vma->vm_page_prot,
-+ mmapcmd.dom)) < 0)
-+ goto mmap_out;
-+
-+ p++;
-+ va += msg.npages << PAGE_SHIFT;
++ /* Do not allow range to wrap the address space. */
++ rc = -EINVAL;
++ if ((msg->npages > (LONG_MAX >> PAGE_SHIFT)) ||
++ ((unsigned long)(msg->npages << PAGE_SHIFT) >= -va))
++ goto mmap_out;
++
++ /* Range chunks must be contiguous in va space. */
++ if ((msg->va != va) ||
++ ((msg->va+(msg->npages<<PAGE_SHIFT)) > vma->vm_end))
++ goto mmap_out;
++
++ if ((rc = direct_remap_pfn_range(
++ vma,
++ msg->va & PAGE_MASK,
++ msg->mfn,
++ msg->npages << PAGE_SHIFT,
++ vma->vm_page_prot,
++ mmapcmd.dom)) < 0)
++ goto mmap_out;
++
++ va += msg->npages << PAGE_SHIFT;
++ msg++;
++ i++;
++ }
+ }
+
+ rc = 0;
+
+ mmap_out:
+ up_write(&mm->mmap_sem);
++ list_for_each_safe(l,l2,&pagelist)
++ free_page((unsigned long)l);
+ ret = rc;
+ }
++#undef MMAP_NR_PER_PAGE
+ break;
+
+ case IOCTL_PRIVCMD_MMAPBATCH: {
++#define MMAPBATCH_NR_PER_PAGE (unsigned long)((PAGE_SIZE-sizeof(struct list_head))/sizeof(unsigned long))
+ privcmd_mmapbatch_t m;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+ xen_pfn_t __user *p;
-+ unsigned long addr, mfn, nr_pages;
++ unsigned long addr, *mfn, nr_pages;
+ int i;
++ LIST_HEAD(pagelist);
++ struct list_head *l, *l2;
+
+ if (!is_initial_xendomain())
+ return -EPERM;
@@ -103208,34 +149575,74 @@ diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/privcmd.c linux-2.6.18-xen-3.2.0/d
+ if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT)))
+ return -EINVAL;
+
++ p = m.arr;
++ for (i=0; i<nr_pages; ) {
++ int nr = min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
++
++ ret = -ENOMEM;
++ l = (struct list_head *)__get_free_page(GFP_KERNEL);
++ if (l == NULL)
++ goto mmapbatch_out;
++
++ INIT_LIST_HEAD(l);
++ list_add_tail(l, &pagelist);
++
++ mfn = (unsigned long*)(l + 1);
++ ret = -EFAULT;
++ if (copy_from_user(mfn, p, nr*sizeof(*mfn)))
++ goto mmapbatch_out;
++
++ i += nr; p+= nr;
++ }
++
+ down_write(&mm->mmap_sem);
+
+ vma = find_vma(mm, m.addr);
++ ret = -EINVAL;
+ if (!vma ||
+ (m.addr != vma->vm_start) ||
+ ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
+ !privcmd_enforce_singleshot_mapping(vma)) {
+ up_write(&mm->mmap_sem);
-+ return -EINVAL;
++ goto mmapbatch_out;
+ }
+
+ p = m.arr;
+ addr = m.addr;
-+ for (i = 0; i < nr_pages; i++, addr += PAGE_SIZE, p++) {
-+ if (get_user(mfn, p)) {
-+ up_write(&mm->mmap_sem);
-+ return -EFAULT;
++ i = 0;
++ ret = 0;
++ list_for_each(l, &pagelist) {
++ int nr = i + min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
++ mfn = (unsigned long *)(l + 1);
++
++ while (i<nr) {
++ if(direct_remap_pfn_range(vma, addr & PAGE_MASK,
++ *mfn, PAGE_SIZE,
++ vma->vm_page_prot, m.dom) < 0) {
++ *mfn |= 0xf0000000U;
++ ret++;
++ }
++ mfn++; i++; addr += PAGE_SIZE;
+ }
-+
-+ ret = direct_remap_pfn_range(vma, addr & PAGE_MASK,
-+ mfn, PAGE_SIZE,
-+ vma->vm_page_prot, m.dom);
-+ if (ret < 0)
-+ put_user(0xF0000000 | mfn, p);
+ }
+
+ up_write(&mm->mmap_sem);
-+ ret = 0;
++ if (ret > 0) {
++ p = m.arr;
++ i = 0;
++ ret = 0;
++ list_for_each(l, &pagelist) {
++ int nr = min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
++ mfn = (unsigned long *)(l + 1);
++ if (copy_to_user(p, mfn, nr*sizeof(*mfn)))
++ ret = -EFAULT;
++ i += nr; p += nr;
++ }
++ }
++ mmapbatch_out:
++ list_for_each_safe(l,l2,&pagelist)
++ free_page((unsigned long)l);
++#undef MMAPBATCH_NR_PER_PAGE
+ }
+ break;
+
@@ -103261,11 +149668,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/privcmd.c linux-2.6.18-xen-3.2.0/d
+
+static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
+{
-+#ifndef __powerpc__ /* PowerPC has a trick to safely do this. */
+ /* Unsupported for auto-translate guests. */
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return -ENOSYS;
-+#endif
+
+ /* DONTCOPY is essential for Xen as copy_page_range is broken. */
+ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
@@ -103316,17 +149721,22198 @@ diff -rpuN linux-2.6.18.8/drivers/xen/privcmd/privcmd.c linux-2.6.18-xen-3.2.0/d
+}
+
+__initcall(privcmd_init);
-diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/Makefile
---- linux-2.6.18.8/drivers/xen/tpmback/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/Makefile 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/scsiback/common.h linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/common.h
+--- linux-2.6.18.8/drivers/xen/scsiback/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/common.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,181 @@
++/*
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * Based on the blkback driver code.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#ifndef __SCSIIF__BACKEND__COMMON_H__
++#define __SCSIIF__BACKEND__COMMON_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/kthread.h>
++#include <linux/blkdev.h>
++#include <linux/list.h>
++#include <linux/kthread.h>
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_host.h>
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_dbg.h>
++#include <scsi/scsi_eh.h>
++#include <asm/io.h>
++#include <asm/setup.h>
++#include <asm/pgalloc.h>
++#include <asm/delay.h>
++#include <xen/evtchn.h>
++#include <asm/hypervisor.h>
++#include <xen/gnttab.h>
++#include <xen/driver_util.h>
++#include <xen/xenbus.h>
++#include <xen/interface/io/ring.h>
++#include <xen/interface/grant_table.h>
++#include <xen/interface/io/vscsiif.h>
++
++
++#define DPRINTK(_f, _a...) \
++ pr_debug("(file=%s, line=%d) " _f, \
++ __FILE__ , __LINE__ , ## _a )
++
++struct ids_tuple {
++ unsigned int hst; /* host */
++ unsigned int chn; /* channel */
++ unsigned int tgt; /* target */
++ unsigned int lun; /* LUN */
++};
++
++struct v2p_entry {
++ struct ids_tuple v; /* translate from */
++ struct scsi_device *sdev; /* translate to */
++ struct list_head l;
++};
++
++struct vscsibk_info {
++ struct xenbus_device *dev;
++
++ domid_t domid;
++ unsigned int evtchn;
++ unsigned int irq;
++
++ struct vscsiif_back_ring ring;
++ struct vm_struct *ring_area;
++ grant_handle_t shmem_handle;
++ grant_ref_t shmem_ref;
++
++ spinlock_t ring_lock;
++ atomic_t nr_unreplied_reqs;
++
++ spinlock_t v2p_lock;
++ struct list_head v2p_entry_lists;
++
++ struct task_struct *kthread;
++ wait_queue_head_t waiting_to_free;
++ wait_queue_head_t wq;
++ unsigned int waiting_reqs;
++ struct page **mmap_pages;
++
++};
++
++typedef struct {
++ unsigned char act;
++ struct vscsibk_info *info;
++ struct scsi_device *sdev;
++
++ uint16_t rqid;
++
++ uint8_t nr_segments;
++ uint8_t cmnd[VSCSIIF_MAX_COMMAND_SIZE];
++ uint8_t cmd_len;
++
++ uint8_t sc_data_direction;
++ uint16_t timeout_per_command;
++
++ uint32_t request_bufflen;
++ struct scatterlist *sgl;
++ grant_ref_t gref[VSCSIIF_SG_TABLESIZE];
++
++ int32_t rslt;
++ uint32_t resid;
++ uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE];
++
++ struct list_head free_list;
++} pending_req_t;
++
++
++
++#define scsiback_get(_b) (atomic_inc(&(_b)->nr_unreplied_reqs))
++#define scsiback_put(_b) \
++ do { \
++ if (atomic_dec_and_test(&(_b)->nr_unreplied_reqs)) \
++ wake_up(&(_b)->waiting_to_free);\
++ } while (0)
++
++#define VSCSIIF_TIMEOUT (900*HZ)
++
++
++irqreturn_t scsiback_intr(int, void *, struct pt_regs *);
++int scsiback_init_sring(struct vscsibk_info *info,
++ unsigned long ring_ref, unsigned int evtchn);
++int scsiback_schedule(void *data);
++
++
++struct vscsibk_info *vscsibk_info_alloc(domid_t domid);
++void scsiback_free(struct vscsibk_info *info);
++void scsiback_disconnect(struct vscsibk_info *info);
++int __init scsiback_interface_init(void);
++void scsiback_interface_exit(void);
++int scsiback_xenbus_init(void);
++void scsiback_xenbus_unregister(void);
++
++void scsiback_init_translation_table(struct vscsibk_info *info);
++
++int scsiback_add_translation_entry(struct vscsibk_info *info,
++ struct scsi_device *sdev, struct ids_tuple *v);
++
++int scsiback_del_translation_entry(struct vscsibk_info *info,
++ struct ids_tuple *v);
++struct scsi_device *scsiback_do_translation(struct vscsibk_info *info,
++ struct ids_tuple *v);
++void scsiback_release_translation_entry(struct vscsibk_info *info);
++
++
++void scsiback_cmd_exec(pending_req_t *pending_req);
++void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
++ uint32_t resid, pending_req_t *pending_req);
++void scsiback_fast_flush_area(pending_req_t *req);
++
++void scsiback_rsp_emulation(pending_req_t *pending_req);
++void scsiback_req_emulation_or_cmdexec(pending_req_t *pending_req);
++void scsiback_emulation_init(void);
++
++
++#endif /* __SCSIIF__BACKEND__COMMON_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/scsiback/emulate.c linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/emulate.c
+--- linux-2.6.18.8/drivers/xen/scsiback/emulate.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/emulate.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,454 @@
++/*
++ * Xen SCSI backend driver
++ *
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
++#include "common.h"
++
++/* Following SCSI commands are not defined in scsi/scsi.h */
++#define EXTENDED_COPY 0x83 /* EXTENDED COPY command */
++#define REPORT_ALIASES 0xa3 /* REPORT ALIASES command */
++#define CHANGE_ALIASES 0xa4 /* CHANGE ALIASES command */
++#define SET_PRIORITY 0xa4 /* SET PRIORITY command */
++
++
++/*
++ The bitmap in order to control emulation.
++ (Bit 3 to 7 are reserved for future use.)
++*/
++#define VSCSIIF_NEED_CMD_EXEC 0x01 /* If this bit is set, cmd exec */
++ /* is required. */
++#define VSCSIIF_NEED_EMULATE_REQBUF 0x02 /* If this bit is set, need */
++ /* emulation reqest buff before */
++ /* cmd exec. */
++#define VSCSIIF_NEED_EMULATE_RSPBUF 0x04 /* If this bit is set, need */
++ /* emulation resp buff after */
++ /* cmd exec. */
++
++/* Additional Sense Code (ASC) used */
++#define NO_ADDITIONAL_SENSE 0x0
++#define LOGICAL_UNIT_NOT_READY 0x4
++#define UNRECOVERED_READ_ERR 0x11
++#define PARAMETER_LIST_LENGTH_ERR 0x1a
++#define INVALID_OPCODE 0x20
++#define ADDR_OUT_OF_RANGE 0x21
++#define INVALID_FIELD_IN_CDB 0x24
++#define INVALID_FIELD_IN_PARAM_LIST 0x26
++#define POWERON_RESET 0x29
++#define SAVING_PARAMS_UNSUP 0x39
++#define THRESHOLD_EXCEEDED 0x5d
++#define LOW_POWER_COND_ON 0x5e
++
++
++
++/* Number os SCSI op_code */
++#define VSCSI_MAX_SCSI_OP_CODE 256
++static unsigned char bitmap[VSCSI_MAX_SCSI_OP_CODE];
++
++
++
++/*
++ Emulation routines for each SCSI op_code.
++*/
++static void (*pre_function[VSCSI_MAX_SCSI_OP_CODE])(pending_req_t *, void *);
++static void (*post_function[VSCSI_MAX_SCSI_OP_CODE])(pending_req_t *, void *);
++
++
++static const int check_condition_result =
++ (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++
++static void scsiback_mk_sense_buffer(uint8_t *data, uint8_t key,
++ uint8_t asc, uint8_t asq)
++{
++ data[0] = 0x70; /* fixed, current */
++ data[2] = key;
++ data[7] = 0xa; /* implies 18 byte sense buffer */
++ data[12] = asc;
++ data[13] = asq;
++}
++
++static void resp_not_supported_cmd(pending_req_t *pending_req, void *data)
++{
++ scsiback_mk_sense_buffer(pending_req->sense_buffer, ILLEGAL_REQUEST,
++ INVALID_OPCODE, 0);
++ pending_req->resid = 0;
++ pending_req->rslt = check_condition_result;
++}
++
++
++static int __copy_to_sg(struct scatterlist *sg, unsigned int nr_sg,
++ void *buf, unsigned int buflen)
++{
++ void *from = buf;
++ void *to;
++ unsigned int from_rest = buflen;
++ unsigned int to_capa;
++ unsigned int copy_size = 0;
++ unsigned int i;
++ unsigned long pfn;
++
++ for (i = 0; i < nr_sg; i++) {
++ if (sg->page == NULL) {
++ printk(KERN_WARNING "%s: inconsistent length field in "
++ "scatterlist\n", __FUNCTION__);
++ return -ENOMEM;
++ }
++
++ to_capa = sg->length;
++ copy_size = min_t(unsigned int, to_capa, from_rest);
++
++ pfn = page_to_pfn(sg->page);
++ to = pfn_to_kaddr(pfn) + (sg->offset);
++ memcpy(to, from, copy_size);
++
++ from_rest -= copy_size;
++ if (from_rest == 0) {
++ return 0;
++ }
++
++ sg++;
++ from += copy_size;
++ }
++
++ printk(KERN_WARNING "%s: no space in scatterlist\n",
++ __FUNCTION__);
++ return -ENOMEM;
++}
++
++static int __copy_from_sg(struct scatterlist *sg, unsigned int nr_sg,
++ void *buf, unsigned int buflen)
++{
++ void *from;
++ void *to = buf;
++ unsigned int from_rest;
++ unsigned int to_capa = buflen;
++ unsigned int copy_size;
++ unsigned int i;
++ unsigned long pfn;
++
++ for (i = 0; i < nr_sg; i++) {
++ if (sg->page == NULL) {
++ printk(KERN_WARNING "%s: inconsistent length field in "
++ "scatterlist\n", __FUNCTION__);
++ return -ENOMEM;
++ }
++
++ from_rest = sg->length;
++ if ((from_rest > 0) && (to_capa < from_rest)) {
++ printk(KERN_WARNING
++ "%s: no space in destination buffer\n",
++ __FUNCTION__);
++ return -ENOMEM;
++ }
++ copy_size = from_rest;
++
++ pfn = page_to_pfn(sg->page);
++ from = pfn_to_kaddr(pfn) + (sg->offset);
++ memcpy(to, from, copy_size);
++
++ to_capa -= copy_size;
++
++ sg++;
++ to += copy_size;
++ }
++
++ return 0;
++}
++
++static int __nr_luns_under_host(struct vscsibk_info *info)
++{
++ struct v2p_entry *entry;
++ struct list_head *head = &(info->v2p_entry_lists);
++ unsigned long flags;
++ int lun_cnt = 0;
++
++ spin_lock_irqsave(&info->v2p_lock, flags);
++ list_for_each_entry(entry, head, l) {
++ lun_cnt++;
++ }
++ spin_unlock_irqrestore(&info->v2p_lock, flags);
++
++ return (lun_cnt);
++}
++
++
++/* REPORT LUNS Define*/
++#define VSCSI_REPORT_LUNS_HEADER 8
++#define VSCSI_REPORT_LUNS_RETRY 3
++
++/* quoted scsi_debug.c/resp_report_luns() */
++static void __report_luns(pending_req_t *pending_req, void *data)
++{
++ struct vscsibk_info *info = pending_req->info;
++ unsigned int channel = pending_req->sdev->channel;
++ unsigned int target = pending_req->sdev->id;
++ unsigned int nr_seg = pending_req->nr_segments;
++ unsigned char *cmd = (unsigned char *)pending_req->cmnd;
++
++ unsigned char *buff = NULL;
++ unsigned char alloc_len;
++ unsigned int alloc_luns = 0;
++ unsigned int req_bufflen = 0;
++ unsigned int actual_len = 0;
++ unsigned int retry_cnt = 0;
++ int select_report = (int)cmd[2];
++ int i, lun_cnt = 0, lun, upper, err = 0;
++
++ struct v2p_entry *entry;
++ struct list_head *head = &(info->v2p_entry_lists);
++ unsigned long flags;
++
++ struct scsi_lun *one_lun;
++
++ req_bufflen = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
++ if ((req_bufflen < 4) || (select_report != 0))
++ goto fail;
++
++ alloc_luns = __nr_luns_under_host(info);
++ alloc_len = sizeof(struct scsi_lun) * alloc_luns
++ + VSCSI_REPORT_LUNS_HEADER;
++retry:
++ if ((buff = kmalloc(alloc_len, GFP_KERNEL)) == NULL) {
++ printk(KERN_ERR "scsiback:%s kmalloc err\n", __FUNCTION__);
++ goto fail;
++ }
++
++ memset(buff, 0, alloc_len);
++
++ one_lun = (struct scsi_lun *) &buff[8];
++ spin_lock_irqsave(&info->v2p_lock, flags);
++ list_for_each_entry(entry, head, l) {
++ if ((entry->v.chn == channel) &&
++ (entry->v.tgt == target)) {
++
++ /* check overflow */
++ if (lun_cnt >= alloc_luns) {
++ spin_unlock_irqrestore(&info->v2p_lock,
++ flags);
++
++ if (retry_cnt < VSCSI_REPORT_LUNS_RETRY) {
++ retry_cnt++;
++ if (buff)
++ kfree(buff);
++ goto retry;
++ }
++
++ goto fail;
++ }
++
++ lun = entry->v.lun;
++ upper = (lun >> 8) & 0x3f;
++ if (upper)
++ one_lun[lun_cnt].scsi_lun[0] = upper;
++ one_lun[lun_cnt].scsi_lun[1] = lun & 0xff;
++ lun_cnt++;
++ }
++ }
++
++ spin_unlock_irqrestore(&info->v2p_lock, flags);
++
++ buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff;
++ buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff;
++
++ actual_len = lun_cnt * sizeof(struct scsi_lun)
++ + VSCSI_REPORT_LUNS_HEADER;
++ req_bufflen = 0;
++ for (i = 0; i < nr_seg; i++)
++ req_bufflen += pending_req->sgl[i].length;
++
++ err = __copy_to_sg(pending_req->sgl, nr_seg, buff,
++ min(req_bufflen, actual_len));
++ if (err)
++ goto fail;
++
++ memset(pending_req->sense_buffer, 0, VSCSIIF_SENSE_BUFFERSIZE);
++ pending_req->rslt = 0x00;
++ pending_req->resid = req_bufflen - min(req_bufflen, actual_len);
++
++ kfree(buff);
++ return;
++
++fail:
++ scsiback_mk_sense_buffer(pending_req->sense_buffer, ILLEGAL_REQUEST,
++ INVALID_FIELD_IN_CDB, 0);
++ pending_req->rslt = check_condition_result;
++ pending_req->resid = 0;
++ if (buff)
++ kfree(buff);
++ return;
++}
++
++
++
++int __pre_do_emulation(pending_req_t *pending_req, void *data)
++{
++ uint8_t op_code = pending_req->cmnd[0];
++
++ if ((bitmap[op_code] & VSCSIIF_NEED_EMULATE_REQBUF) &&
++ pre_function[op_code] != NULL) {
++ pre_function[op_code](pending_req, data);
++ }
++
++ /*
++ 0: no need for native driver call, so should return immediately.
++ 1: non emulation or should call native driver
++ after modifing the request buffer.
++ */
++ return !!(bitmap[op_code] & VSCSIIF_NEED_CMD_EXEC);
++}
++
++void scsiback_rsp_emulation(pending_req_t *pending_req)
++{
++ uint8_t op_code = pending_req->cmnd[0];
++
++ if ((bitmap[op_code] & VSCSIIF_NEED_EMULATE_RSPBUF) &&
++ post_function[op_code] != NULL) {
++ post_function[op_code](pending_req, NULL);
++ }
++
++ return;
++}
++
++
++void scsiback_req_emulation_or_cmdexec(pending_req_t *pending_req)
++{
++ if (__pre_do_emulation(pending_req, NULL)) {
++ scsiback_cmd_exec(pending_req);
++ }
++ else {
++ scsiback_fast_flush_area(pending_req);
++ scsiback_do_resp_with_sense(pending_req->sense_buffer,
++ pending_req->rslt, pending_req->resid, pending_req);
++ }
++}
++
++
++/*
++ Following are not customizable functions.
++*/
++void scsiback_emulation_init(void)
++{
++ int i;
++
++ /* Initialize to default state */
++ for (i = 0; i < VSCSI_MAX_SCSI_OP_CODE; i++) {
++ bitmap[i] = (VSCSIIF_NEED_EMULATE_REQBUF |
++ VSCSIIF_NEED_EMULATE_RSPBUF);
++ pre_function[i] = resp_not_supported_cmd;
++ post_function[i] = NULL;
++ /* means,
++ - no need for pre-emulation
++ - no need for post-emulation
++ - call native driver
++ */
++ }
++
++ /*
++ Register appropriate functions below as you need.
++ (See scsi/scsi.h for definition of SCSI op_code.)
++ */
++
++ /*
++ This command is Non emulation.
++ */
++ bitmap[TEST_UNIT_READY] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[TEST_UNIT_READY] = NULL;
++ post_function[TEST_UNIT_READY] = NULL;
++
++ bitmap[REZERO_UNIT] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[REZERO_UNIT] = NULL;
++ post_function[REZERO_UNIT] = NULL;
++
++ bitmap[REQUEST_SENSE] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[REQUEST_SENSE] = NULL;
++ post_function[REQUEST_SENSE] = NULL;
++
++ bitmap[FORMAT_UNIT] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[FORMAT_UNIT] = NULL;
++ post_function[FORMAT_UNIT] = NULL;
++
++ bitmap[READ_BLOCK_LIMITS] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[READ_BLOCK_LIMITS] = NULL;
++ post_function[READ_BLOCK_LIMITS] = NULL;
++
++ bitmap[READ_6] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[READ_6] = NULL;
++ post_function[READ_6] = NULL;
++
++ bitmap[WRITE_6] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[WRITE_6] = NULL;
++ post_function[WRITE_6] = NULL;
++
++ bitmap[WRITE_FILEMARKS] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[WRITE_FILEMARKS] = NULL;
++ post_function[WRITE_FILEMARKS] = NULL;
++
++ bitmap[SPACE] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[SPACE] = NULL;
++ post_function[SPACE] = NULL;
++
++ bitmap[INQUIRY] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[INQUIRY] = NULL;
++ post_function[INQUIRY] = NULL;
++
++ bitmap[ERASE] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[ERASE] = NULL;
++ post_function[ERASE] = NULL;
++
++ bitmap[MODE_SENSE] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[MODE_SENSE] = NULL;
++ post_function[MODE_SENSE] = NULL;
++
++ bitmap[SEND_DIAGNOSTIC] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[SEND_DIAGNOSTIC] = NULL;
++ post_function[SEND_DIAGNOSTIC] = NULL;
++
++ bitmap[READ_CAPACITY] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[READ_CAPACITY] = NULL;
++ post_function[READ_CAPACITY] = NULL;
++
++ bitmap[READ_10] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[READ_10] = NULL;
++ post_function[READ_10] = NULL;
++
++ bitmap[WRITE_10] = VSCSIIF_NEED_CMD_EXEC;
++ pre_function[WRITE_10] = NULL;
++ post_function[WRITE_10] = NULL;
++
++ /*
++ This command is Full emulation.
++ */
++ pre_function[REPORT_LUNS] = __report_luns;
++ bitmap[REPORT_LUNS] = (VSCSIIF_NEED_EMULATE_REQBUF |
++ VSCSIIF_NEED_EMULATE_RSPBUF);
++
++ return;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/scsiback/interface.c linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/interface.c
+--- linux-2.6.18.8/drivers/xen/scsiback/interface.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/interface.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,182 @@
++/*
++ * interface management.
++ *
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * Based on the blkback driver code.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_host.h>
++#include <scsi/scsi_device.h>
++#include "common.h"
++
++#include <xen/evtchn.h>
++#include <linux/kthread.h>
++
++
++static kmem_cache_t *scsiback_cachep;
++
++struct vscsibk_info *vscsibk_info_alloc(domid_t domid)
++{
++ struct vscsibk_info *info;
++
++ info = kmem_cache_alloc(scsiback_cachep, GFP_KERNEL);
++ if (!info)
++ return ERR_PTR(-ENOMEM);
++
++ memset(info, 0, sizeof(*info));
++ info->domid = domid;
++ spin_lock_init(&info->ring_lock);
++ atomic_set(&info->nr_unreplied_reqs, 0);
++ init_waitqueue_head(&info->wq);
++ init_waitqueue_head(&info->waiting_to_free);
++
++ return info;
++}
++
++static int map_frontend_page( struct vscsibk_info *info,
++ unsigned long ring_ref)
++{
++ struct gnttab_map_grant_ref op;
++ int err;
++
++ gnttab_set_map_op(&op, (unsigned long)info->ring_area->addr,
++ GNTMAP_host_map, ring_ref,
++ info->domid);
++
++ err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
++ BUG_ON(err);
++
++ if (op.status) {
++ printk(KERN_ERR "scsiback: Grant table operation failure !\n");
++ return op.status;
++ }
++
++ info->shmem_ref = ring_ref;
++ info->shmem_handle = op.handle;
++
++ return (GNTST_okay);
++}
++
++static void unmap_frontend_page(struct vscsibk_info *info)
++{
++ struct gnttab_unmap_grant_ref op;
++ int err;
++
++ gnttab_set_unmap_op(&op, (unsigned long)info->ring_area->addr,
++ GNTMAP_host_map, info->shmem_handle);
++
++ err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
++ BUG_ON(err);
++
++}
++
++int scsiback_init_sring(struct vscsibk_info *info,
++ unsigned long ring_ref, unsigned int evtchn)
++{
++ struct vscsiif_sring *sring;
++ int err;
++
++ if (info->irq) {
++ printk(KERN_ERR "scsiback: Already connected through?\n");
++ return -1;
++ }
++
++ info->ring_area = alloc_vm_area(PAGE_SIZE);
++ if (!info)
++ return -ENOMEM;
++
++ err = map_frontend_page(info, ring_ref);
++ if (err)
++ goto free_vm;
++
++ sring = (struct vscsiif_sring *) info->ring_area->addr;
++ BACK_RING_INIT(&info->ring, sring, PAGE_SIZE);
++
++ err = bind_interdomain_evtchn_to_irqhandler(
++ info->domid, evtchn,
++ scsiback_intr, 0, "vscsiif-backend", info);
++
++ if (err < 0)
++ goto unmap_page;
++
++ info->irq = err;
++
++ return 0;
++
++unmap_page:
++ unmap_frontend_page(info);
++free_vm:
++ free_vm_area(info->ring_area);
++
++ return err;
++}
++
++void scsiback_disconnect(struct vscsibk_info *info)
++{
++ if (info->kthread) {
++ kthread_stop(info->kthread);
++ info->kthread = NULL;
++ }
++
++ wait_event(info->waiting_to_free,
++ atomic_read(&info->nr_unreplied_reqs) == 0);
++
++ if (info->irq) {
++ unbind_from_irqhandler(info->irq, info);
++ info->irq = 0;
++ }
++
++ if (info->ring.sring) {
++ unmap_frontend_page(info);
++ free_vm_area(info->ring_area);
++ info->ring.sring = NULL;
++ }
++}
++
++void scsiback_free(struct vscsibk_info *info)
++{
++ kmem_cache_free(scsiback_cachep, info);
++}
++
++int __init scsiback_interface_init(void)
++{
++ scsiback_cachep = kmem_cache_create("vscsiif_cache",
++ sizeof(struct vscsibk_info), 0, 0, NULL, NULL);
++ if (!scsiback_cachep) {
++ printk(KERN_ERR "scsiback: can't init scsi cache\n");
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++void scsiback_interface_exit(void)
++{
++ kmem_cache_destroy(scsiback_cachep);
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/scsiback/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/Makefile
+--- linux-2.6.18.8/drivers/xen/scsiback/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,4 @@
++obj-$(CONFIG_XEN_SCSI_BACKEND) := xen-scsibk.o
+
-+obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmbk.o
++xen-scsibk-y := interface.o scsiback.o xenbus.o translate.o emulate.o
+
-+tpmbk-y += tpmback.o interface.o xenbus.o
-diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/common.h linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/common.h
---- linux-2.6.18.8/drivers/xen/tpmback/common.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/common.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/scsiback/scsiback.c linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/scsiback.c
+--- linux-2.6.18.8/drivers/xen/scsiback/scsiback.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/scsiback.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,717 @@
++/*
++ * Xen SCSI backend driver
++ *
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * Based on the blkback driver code.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <linux/spinlock.h>
++#include <linux/kthread.h>
++#include <linux/list.h>
++#include <linux/delay.h>
++#include <xen/balloon.h>
++#include <asm/hypervisor.h>
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_host.h>
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_dbg.h>
++#include <scsi/scsi_eh.h>
++
++#include "common.h"
++
++
++struct list_head pending_free;
++DEFINE_SPINLOCK(pending_free_lock);
++DECLARE_WAIT_QUEUE_HEAD(pending_free_wq);
++
++int vscsiif_reqs = VSCSIIF_BACK_MAX_PENDING_REQS;
++module_param_named(reqs, vscsiif_reqs, int, 0);
++MODULE_PARM_DESC(reqs, "Number of scsiback requests to allocate");
++
++static unsigned int log_print_stat = 0;
++module_param(log_print_stat, int, 0644);
++
++#define SCSIBACK_INVALID_HANDLE (~0)
++
++static pending_req_t *pending_reqs;
++static struct page **pending_pages;
++static grant_handle_t *pending_grant_handles;
++
++static int vaddr_pagenr(pending_req_t *req, int seg)
++{
++ return (req - pending_reqs) * VSCSIIF_SG_TABLESIZE + seg;
++}
++
++static unsigned long vaddr(pending_req_t *req, int seg)
++{
++ unsigned long pfn = page_to_pfn(pending_pages[vaddr_pagenr(req, seg)]);
++ return (unsigned long)pfn_to_kaddr(pfn);
++}
++
++#define pending_handle(_req, _seg) \
++ (pending_grant_handles[vaddr_pagenr(_req, _seg)])
++
++
++void scsiback_fast_flush_area(pending_req_t *req)
++{
++ struct gnttab_unmap_grant_ref unmap[VSCSIIF_SG_TABLESIZE];
++ unsigned int i, invcount = 0;
++ grant_handle_t handle;
++ int err;
++
++ if (req->nr_segments) {
++ for (i = 0; i < req->nr_segments; i++) {
++ handle = pending_handle(req, i);
++ if (handle == SCSIBACK_INVALID_HANDLE)
++ continue;
++ gnttab_set_unmap_op(&unmap[i], vaddr(req, i),
++ GNTMAP_host_map, handle);
++ pending_handle(req, i) = SCSIBACK_INVALID_HANDLE;
++ invcount++;
++ }
++
++ err = HYPERVISOR_grant_table_op(
++ GNTTABOP_unmap_grant_ref, unmap, invcount);
++ BUG_ON(err);
++ kfree(req->sgl);
++ }
++
++ return;
++}
++
++
++static pending_req_t * alloc_req(struct vscsibk_info *info)
++{
++ pending_req_t *req = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&pending_free_lock, flags);
++ if (!list_empty(&pending_free)) {
++ req = list_entry(pending_free.next, pending_req_t, free_list);
++ list_del(&req->free_list);
++ }
++ spin_unlock_irqrestore(&pending_free_lock, flags);
++ return req;
++}
++
++
++static void free_req(pending_req_t *req)
++{
++ unsigned long flags;
++ int was_empty;
++
++ spin_lock_irqsave(&pending_free_lock, flags);
++ was_empty = list_empty(&pending_free);
++ list_add(&req->free_list, &pending_free);
++ spin_unlock_irqrestore(&pending_free_lock, flags);
++ if (was_empty)
++ wake_up(&pending_free_wq);
++}
++
++
++static void scsiback_notify_work(struct vscsibk_info *info)
++{
++ info->waiting_reqs = 1;
++ wake_up(&info->wq);
++}
++
++void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
++ uint32_t resid, pending_req_t *pending_req)
++{
++ vscsiif_response_t *ring_res;
++ struct vscsibk_info *info = pending_req->info;
++ int notify;
++ int more_to_do = 1;
++ unsigned long flags;
++
++ DPRINTK("%s\n",__FUNCTION__);
++
++ spin_lock_irqsave(&info->ring_lock, flags);
++
++ ring_res = RING_GET_RESPONSE(&info->ring, info->ring.rsp_prod_pvt);
++ info->ring.rsp_prod_pvt++;
++
++ ring_res->rslt = result;
++ ring_res->rqid = pending_req->rqid;
++
++ if (sense_buffer != NULL) {
++ memcpy(ring_res->sense_buffer, sense_buffer,
++ VSCSIIF_SENSE_BUFFERSIZE);
++ ring_res->sense_len = VSCSIIF_SENSE_BUFFERSIZE;
++ } else {
++ ring_res->sense_len = 0;
++ }
++
++ ring_res->residual_len = resid;
++
++ RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&info->ring, notify);
++ if (info->ring.rsp_prod_pvt == info->ring.req_cons) {
++ RING_FINAL_CHECK_FOR_REQUESTS(&info->ring, more_to_do);
++ } else if (RING_HAS_UNCONSUMED_REQUESTS(&info->ring)) {
++ more_to_do = 1;
++ }
++
++ spin_unlock_irqrestore(&info->ring_lock, flags);
++
++ if (more_to_do)
++ scsiback_notify_work(info);
++
++ if (notify)
++ notify_remote_via_irq(info->irq);
++
++ free_req(pending_req);
++}
++
++static void scsiback_print_status(char *sense_buffer, int errors,
++ pending_req_t *pending_req)
++{
++ struct scsi_device *sdev = pending_req->sdev;
++
++ printk(KERN_ERR "scsiback: %d:%d:%d:%d ",sdev->host->host_no,
++ sdev->channel, sdev->id, sdev->lun);
++ printk(KERN_ERR "status = 0x%02x, message = 0x%02x, host = 0x%02x, driver = 0x%02x\n",
++ status_byte(errors), msg_byte(errors),
++ host_byte(errors), driver_byte(errors));
++
++ printk(KERN_ERR "scsiback: cmnd[0]=0x%02X\n",
++ pending_req->cmnd[0]);
++
++ if (CHECK_CONDITION & status_byte(errors))
++ __scsi_print_sense("scsiback", sense_buffer, SCSI_SENSE_BUFFERSIZE);
++}
++
++
++static void scsiback_cmd_done(struct request *req, int errors)
++{
++ pending_req_t *pending_req = req->end_io_data;
++ unsigned char *sense_buffer;
++ unsigned int resid;
++
++ sense_buffer = req->sense;
++ resid = req->data_len;
++
++ if (errors != 0) {
++ if (log_print_stat)
++ scsiback_print_status(sense_buffer, errors, pending_req);
++ }
++
++ scsiback_rsp_emulation(pending_req);
++
++ scsiback_fast_flush_area(pending_req);
++ scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req);
++ scsiback_put(pending_req->info);
++
++ __blk_put_request(req->q, req);
++}
++
++
++static int scsiback_gnttab_data_map(vscsiif_request_t *ring_req,
++ pending_req_t *pending_req)
++{
++ u32 flags;
++ int write;
++ int i, err = 0;
++ unsigned int data_len = 0;
++ struct gnttab_map_grant_ref map[VSCSIIF_SG_TABLESIZE];
++ struct vscsibk_info *info = pending_req->info;
++
++ int data_dir = (int)pending_req->sc_data_direction;
++ unsigned int nr_segments = (unsigned int)pending_req->nr_segments;
++
++ write = (data_dir == DMA_TO_DEVICE);
++
++ if (nr_segments) {
++ /* free of (sgl) in fast_flush_area()*/
++ pending_req->sgl = kmalloc(sizeof(struct scatterlist) * nr_segments,
++ GFP_KERNEL);
++ if (!pending_req->sgl) {
++ printk(KERN_ERR "scsiback: %s: kmalloc() error.\n", __FUNCTION__);
++ return -ENOMEM;
++ }
++
++ for (i = 0; i < nr_segments; i++) {
++ flags = GNTMAP_host_map;
++ if (write)
++ flags |= GNTMAP_readonly;
++ gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags,
++ ring_req->seg[i].gref,
++ info->domid);
++ }
++
++ err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nr_segments);
++ BUG_ON(err);
++
++ for (i = 0; i < nr_segments; i++) {
++ if (unlikely(map[i].status != 0)) {
++ printk(KERN_ERR "scsiback: invalid buffer -- could not remap it\n");
++ map[i].handle = SCSIBACK_INVALID_HANDLE;
++ err |= 1;
++ }
++
++ pending_handle(pending_req, i) = map[i].handle;
++
++ if (err)
++ continue;
++
++ set_phys_to_machine(__pa(vaddr(
++ pending_req, i)) >> PAGE_SHIFT,
++ FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
++
++ pending_req->sgl[i].page = virt_to_page(vaddr(pending_req, i));
++ pending_req->sgl[i].offset = ring_req->seg[i].offset;
++ pending_req->sgl[i].length = ring_req->seg[i].length;
++ data_len += pending_req->sgl[i].length;
++
++ barrier();
++ if (pending_req->sgl[i].offset >= PAGE_SIZE ||
++ pending_req->sgl[i].length > PAGE_SIZE ||
++ pending_req->sgl[i].offset + pending_req->sgl[i].length > PAGE_SIZE)
++ err |= 1;
++
++ }
++
++ if (err)
++ goto fail_flush;
++ }
++
++ pending_req->request_bufflen = data_len;
++
++ return 0;
++
++fail_flush:
++ scsiback_fast_flush_area(pending_req);
++ return -ENOMEM;
++}
++
++/* quoted scsi_lib.c/scsi_merge_bio */
++static int scsiback_merge_bio(struct request *rq, struct bio *bio)
++{
++ struct request_queue *q = rq->q;
++
++ bio->bi_flags &= ~(1 << BIO_SEG_VALID);
++ if (rq_data_dir(rq) == WRITE)
++ bio->bi_rw |= (1 << BIO_RW);
++
++ blk_queue_bounce(q, &bio);
++
++ if (!rq->bio)
++ blk_rq_bio_prep(q, rq, bio);
++ else if (!q->back_merge_fn(q, rq, bio))
++ return -EINVAL;
++ else {
++ rq->biotail->bi_next = bio;
++ rq->biotail = bio;
++ rq->hard_nr_sectors += bio_sectors(bio);
++ rq->nr_sectors = rq->hard_nr_sectors;
++ }
++
++ return 0;
++}
++
++
++/* quoted scsi_lib.c/scsi_bi_endio */
++static int scsiback_bi_endio(struct bio *bio, unsigned int bytes_done, int error)
++{
++ if (bio->bi_size)
++ return 1;
++
++ bio_put(bio);
++ return 0;
++}
++
++
++
++/* quoted scsi_lib.c/scsi_req_map_sg . */
++static int request_map_sg(struct request *rq, pending_req_t *pending_req, unsigned int count)
++{
++ struct request_queue *q = rq->q;
++ int nr_pages;
++ unsigned int nsegs = count;
++
++ unsigned int data_len = 0, len, bytes, off;
++ struct page *page;
++ struct bio *bio = NULL;
++ int i, err, nr_vecs = 0;
++
++ for (i = 0; i < nsegs; i++) {
++ page = pending_req->sgl[i].page;
++ off = (unsigned int)pending_req->sgl[i].offset;
++ len = (unsigned int)pending_req->sgl[i].length;
++ data_len += len;
++
++ nr_pages = (len + off + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ while (len > 0) {
++ bytes = min_t(unsigned int, len, PAGE_SIZE - off);
++
++ if (!bio) {
++ nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
++ nr_pages -= nr_vecs;
++ bio = bio_alloc(GFP_KERNEL, nr_vecs);
++ if (!bio) {
++ err = -ENOMEM;
++ goto free_bios;
++ }
++ bio->bi_end_io = scsiback_bi_endio;
++ }
++
++ if (bio_add_pc_page(q, bio, page, bytes, off) !=
++ bytes) {
++ bio_put(bio);
++ err = -EINVAL;
++ goto free_bios;
++ }
++
++ if (bio->bi_vcnt >= nr_vecs) {
++ err = scsiback_merge_bio(rq, bio);
++ if (err) {
++ bio_endio(bio, bio->bi_size, 0);
++ goto free_bios;
++ }
++ bio = NULL;
++ }
++
++ page++;
++ len -= bytes;
++ off = 0;
++ }
++ }
++
++ rq->buffer = rq->data = NULL;
++ rq->data_len = data_len;
++
++ return 0;
++
++free_bios:
++ while ((bio = rq->bio) != NULL) {
++ rq->bio = bio->bi_next;
++ /*
++ * call endio instead of bio_put incase it was bounced
++ */
++ bio_endio(bio, bio->bi_size, 0);
++ }
++
++ return err;
++}
++
++
++void scsiback_cmd_exec(pending_req_t *pending_req)
++{
++ int cmd_len = (int)pending_req->cmd_len;
++ int data_dir = (int)pending_req->sc_data_direction;
++ unsigned int nr_segments = (unsigned int)pending_req->nr_segments;
++ unsigned int timeout;
++ struct request *rq;
++ int write;
++
++ DPRINTK("%s\n",__FUNCTION__);
++
++ /* because it doesn't timeout backend earlier than frontend.*/
++ if (pending_req->timeout_per_command)
++ timeout = pending_req->timeout_per_command * HZ;
++ else
++ timeout = VSCSIIF_TIMEOUT;
++
++ write = (data_dir == DMA_TO_DEVICE);
++ rq = blk_get_request(pending_req->sdev->request_queue, write, GFP_KERNEL);
++
++ rq->flags |= REQ_BLOCK_PC;
++ rq->cmd_len = cmd_len;
++ memcpy(rq->cmd, pending_req->cmnd, cmd_len);
++
++ memset(pending_req->sense_buffer, 0, VSCSIIF_SENSE_BUFFERSIZE);
++ rq->sense = pending_req->sense_buffer;
++ rq->sense_len = 0;
++
++ /* not allowed to retry in backend. */
++ rq->retries = 0;
++ rq->timeout = timeout;
++ rq->end_io_data = pending_req;
++
++ if (nr_segments) {
++
++ if (request_map_sg(rq, pending_req, nr_segments)) {
++ printk(KERN_ERR "scsiback: SG Request Map Error\n");
++ return;
++ }
++ }
++
++ scsiback_get(pending_req->info);
++ blk_execute_rq_nowait(rq->q, NULL, rq, 1, scsiback_cmd_done);
++
++ return ;
++}
++
++
++static void scsiback_device_reset_exec(pending_req_t *pending_req)
++{
++ struct vscsibk_info *info = pending_req->info;
++ int err;
++ struct scsi_device *sdev = pending_req->sdev;
++
++ scsiback_get(info);
++ err = scsi_reset_provider(sdev, SCSI_TRY_RESET_DEVICE);
++
++ scsiback_do_resp_with_sense(NULL, err, 0, pending_req);
++ scsiback_put(info);
++
++ return;
++}
++
++
++irqreturn_t scsiback_intr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ scsiback_notify_work((struct vscsibk_info *)dev_id);
++ return IRQ_HANDLED;
++}
++
++static int prepare_pending_reqs(struct vscsibk_info *info,
++ vscsiif_request_t *ring_req, pending_req_t *pending_req)
++{
++ struct scsi_device *sdev;
++ struct ids_tuple vir;
++ int err = -EINVAL;
++
++ DPRINTK("%s\n",__FUNCTION__);
++
++ pending_req->rqid = ring_req->rqid;
++ pending_req->act = ring_req->act;
++
++ pending_req->info = info;
++
++ vir.chn = ring_req->channel;
++ vir.tgt = ring_req->id;
++ vir.lun = ring_req->lun;
++
++ rmb();
++ sdev = scsiback_do_translation(info, &vir);
++ if (!sdev) {
++ pending_req->sdev = NULL;
++ DPRINTK("scsiback: doesn't exist.\n");
++ err = -ENODEV;
++ goto invalid_value;
++ }
++ pending_req->sdev = sdev;
++
++ /* request range check from frontend */
++ pending_req->sc_data_direction = ring_req->sc_data_direction;
++ barrier();
++ if ((pending_req->sc_data_direction != DMA_BIDIRECTIONAL) &&
++ (pending_req->sc_data_direction != DMA_TO_DEVICE) &&
++ (pending_req->sc_data_direction != DMA_FROM_DEVICE) &&
++ (pending_req->sc_data_direction != DMA_NONE)) {
++ DPRINTK("scsiback: invalid parameter data_dir = %d\n",
++ pending_req->sc_data_direction);
++ err = -EINVAL;
++ goto invalid_value;
++ }
++
++ pending_req->nr_segments = ring_req->nr_segments;
++ barrier();
++ if (pending_req->nr_segments > VSCSIIF_SG_TABLESIZE) {
++ DPRINTK("scsiback: invalid parameter nr_seg = %d\n",
++ pending_req->nr_segments);
++ err = -EINVAL;
++ goto invalid_value;
++ }
++
++ pending_req->cmd_len = ring_req->cmd_len;
++ barrier();
++ if (pending_req->cmd_len > VSCSIIF_MAX_COMMAND_SIZE) {
++ DPRINTK("scsiback: invalid parameter cmd_len = %d\n",
++ pending_req->cmd_len);
++ err = -EINVAL;
++ goto invalid_value;
++ }
++ memcpy(pending_req->cmnd, ring_req->cmnd, pending_req->cmd_len);
++
++ pending_req->timeout_per_command = ring_req->timeout_per_command;
++
++ if(scsiback_gnttab_data_map(ring_req, pending_req)) {
++ DPRINTK("scsiback: invalid buffer\n");
++ err = -EINVAL;
++ goto invalid_value;
++ }
++
++ return 0;
++
++invalid_value:
++ return err;
++}
++
++
++static int scsiback_do_cmd_fn(struct vscsibk_info *info)
++{
++ struct vscsiif_back_ring *ring = &info->ring;
++ vscsiif_request_t *ring_req;
++
++ pending_req_t *pending_req;
++ RING_IDX rc, rp;
++ int err, more_to_do = 0;
++
++ DPRINTK("%s\n",__FUNCTION__);
++
++ rc = ring->req_cons;
++ rp = ring->sring->req_prod;
++ rmb();
++
++ while ((rc != rp)) {
++ if (RING_REQUEST_CONS_OVERFLOW(ring, rc))
++ break;
++ pending_req = alloc_req(info);
++ if (NULL == pending_req) {
++ more_to_do = 1;
++ break;
++ }
++
++ ring_req = RING_GET_REQUEST(ring, rc);
++ ring->req_cons = ++rc;
++
++ err = prepare_pending_reqs(info, ring_req,
++ pending_req);
++ if (err == -EINVAL) {
++ scsiback_do_resp_with_sense(NULL, (DRIVER_ERROR << 24),
++ 0, pending_req);
++ continue;
++ } else if (err == -ENODEV) {
++ scsiback_do_resp_with_sense(NULL, (DID_NO_CONNECT << 16),
++ 0, pending_req);
++ continue;
++ }
++
++ if (pending_req->act == VSCSIIF_ACT_SCSI_CDB) {
++ scsiback_req_emulation_or_cmdexec(pending_req);
++ } else if (pending_req->act == VSCSIIF_ACT_SCSI_RESET) {
++ scsiback_device_reset_exec(pending_req);
++ } else {
++ printk(KERN_ERR "scsiback: invalid parameter for request\n");
++ scsiback_do_resp_with_sense(NULL, (DRIVER_ERROR << 24),
++ 0, pending_req);
++ continue;
++ }
++ }
++
++ if (RING_HAS_UNCONSUMED_REQUESTS(ring))
++ more_to_do = 1;
++
++ /* Yield point for this unbounded loop. */
++ cond_resched();
++
++ return more_to_do;
++}
++
++
++int scsiback_schedule(void *data)
++{
++ struct vscsibk_info *info = (struct vscsibk_info *)data;
++
++ DPRINTK("%s\n",__FUNCTION__);
++
++ while (!kthread_should_stop()) {
++ wait_event_interruptible(
++ info->wq,
++ info->waiting_reqs || kthread_should_stop());
++ wait_event_interruptible(
++ pending_free_wq,
++ !list_empty(&pending_free) || kthread_should_stop());
++
++ info->waiting_reqs = 0;
++ smp_mb();
++
++ if (scsiback_do_cmd_fn(info))
++ info->waiting_reqs = 1;
++ }
++
++ return 0;
++}
++
++
++static int __init scsiback_init(void)
++{
++ int i, mmap_pages;
++
++ if (!is_running_on_xen())
++ return -ENODEV;
++
++ mmap_pages = vscsiif_reqs * VSCSIIF_SG_TABLESIZE;
++
++ pending_reqs = kmalloc(sizeof(pending_reqs[0]) *
++ vscsiif_reqs, GFP_KERNEL);
++ pending_grant_handles = kmalloc(sizeof(pending_grant_handles[0]) *
++ mmap_pages, GFP_KERNEL);
++ pending_pages = alloc_empty_pages_and_pagevec(mmap_pages);
++
++ if (!pending_reqs || !pending_grant_handles || !pending_pages)
++ goto out_of_memory;
++
++ for (i = 0; i < mmap_pages; i++)
++ pending_grant_handles[i] = SCSIBACK_INVALID_HANDLE;
++
++ if (scsiback_interface_init() < 0)
++ goto out_of_kmem;
++
++ memset(pending_reqs, 0, sizeof(pending_reqs));
++ INIT_LIST_HEAD(&pending_free);
++
++ for (i = 0; i < vscsiif_reqs; i++)
++ list_add_tail(&pending_reqs[i].free_list, &pending_free);
++
++ if (scsiback_xenbus_init())
++ goto out_of_xenbus;
++
++ scsiback_emulation_init();
++
++ return 0;
++
++out_of_xenbus:
++ scsiback_xenbus_unregister();
++out_of_kmem:
++ scsiback_interface_exit();
++out_of_memory:
++ kfree(pending_reqs);
++ kfree(pending_grant_handles);
++ free_empty_pages_and_pagevec(pending_pages, mmap_pages);
++ printk(KERN_ERR "scsiback: %s: out of memory\n", __FUNCTION__);
++ return -ENOMEM;
++}
++
++static void __exit scsiback_exit(void)
++{
++ scsiback_xenbus_unregister();
++ scsiback_interface_exit();
++ kfree(pending_reqs);
++ kfree(pending_grant_handles);
++ free_empty_pages_and_pagevec(pending_pages, (vscsiif_reqs * VSCSIIF_SG_TABLESIZE));
++
++}
++
++module_init(scsiback_init);
++module_exit(scsiback_exit);
++
++MODULE_DESCRIPTION("Xen SCSI backend driver");
++MODULE_LICENSE("Dual BSD/GPL");
+diff -rpuN linux-2.6.18.8/drivers/xen/scsiback/translate.c linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/translate.c
+--- linux-2.6.18.8/drivers/xen/scsiback/translate.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/translate.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,168 @@
++/*
++ * Xen SCSI backend driver
++ *
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <linux/list.h>
++#include <linux/gfp.h>
++
++#include "common.h"
++
++/*
++ Initialize the translation entry list
++*/
++void scsiback_init_translation_table(struct vscsibk_info *info)
++{
++ INIT_LIST_HEAD(&info->v2p_entry_lists);
++ spin_lock_init(&info->v2p_lock);
++}
++
++
++/*
++ Add a new translation entry
++*/
++int scsiback_add_translation_entry(struct vscsibk_info *info,
++ struct scsi_device *sdev, struct ids_tuple *v)
++{
++ int err = 0;
++ struct v2p_entry *entry;
++ struct v2p_entry *new;
++ struct list_head *head = &(info->v2p_entry_lists);
++ unsigned long flags;
++
++ spin_lock_irqsave(&info->v2p_lock, flags);
++
++ /* Check double assignment to identical virtual ID */
++ list_for_each_entry(entry, head, l) {
++ if ((entry->v.chn == v->chn) &&
++ (entry->v.tgt == v->tgt) &&
++ (entry->v.lun == v->lun)) {
++ printk(KERN_WARNING "scsiback: Virtual ID is already used. "
++ "Assignment was not performed.\n");
++ err = -EEXIST;
++ goto out;
++ }
++
++ }
++
++ /* Create a new translation entry and add to the list */
++ if ((new = kmalloc(sizeof(struct v2p_entry), GFP_ATOMIC)) == NULL) {
++ printk(KERN_ERR "scsiback: %s: kmalloc() error.\n", __FUNCTION__);
++ err = -ENOMEM;
++ goto out;
++ }
++ new->v = *v;
++ new->sdev = sdev;
++ list_add_tail(&new->l, head);
++
++out:
++ spin_unlock_irqrestore(&info->v2p_lock, flags);
++ return err;
++}
++
++
++/*
++ Delete the translation entry specfied
++*/
++int scsiback_del_translation_entry(struct vscsibk_info *info,
++ struct ids_tuple *v)
++{
++ struct v2p_entry *entry;
++ struct list_head *head = &(info->v2p_entry_lists);
++ unsigned long flags;
++
++ spin_lock_irqsave(&info->v2p_lock, flags);
++ /* Find out the translation entry specified */
++ list_for_each_entry(entry, head, l) {
++ if ((entry->v.chn == v->chn) &&
++ (entry->v.tgt == v->tgt) &&
++ (entry->v.lun == v->lun)) {
++ goto found;
++ }
++ }
++
++ spin_unlock_irqrestore(&info->v2p_lock, flags);
++ return 1;
++
++found:
++ /* Delete the translation entry specfied */
++ scsi_device_put(entry->sdev);
++ list_del(&entry->l);
++ kfree(entry);
++
++ spin_unlock_irqrestore(&info->v2p_lock, flags);
++ return 0;
++}
++
++
++/*
++ Perform virtual to physical translation
++*/
++struct scsi_device *scsiback_do_translation(struct vscsibk_info *info,
++ struct ids_tuple *v)
++{
++ struct v2p_entry *entry;
++ struct list_head *head = &(info->v2p_entry_lists);
++ struct scsi_device *sdev = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&info->v2p_lock, flags);
++ list_for_each_entry(entry, head, l) {
++ if ((entry->v.chn == v->chn) &&
++ (entry->v.tgt == v->tgt) &&
++ (entry->v.lun == v->lun)) {
++ sdev = entry->sdev;
++ goto out;
++ }
++ }
++out:
++ spin_unlock_irqrestore(&info->v2p_lock, flags);
++ return sdev;
++}
++
++
++/*
++ Release the translation entry specfied
++*/
++void scsiback_release_translation_entry(struct vscsibk_info *info)
++{
++ struct v2p_entry *entry, *tmp;
++ struct list_head *head = &(info->v2p_entry_lists);
++ unsigned long flags;
++
++ spin_lock_irqsave(&info->v2p_lock, flags);
++ list_for_each_entry_safe(entry, tmp, head, l) {
++ scsi_device_put(entry->sdev);
++ list_del(&entry->l);
++ kfree(entry);
++ }
++
++ spin_unlock_irqrestore(&info->v2p_lock, flags);
++ return;
++
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/scsiback/xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/xenbus.c
+--- linux-2.6.18.8/drivers/xen/scsiback/xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsiback/xenbus.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,368 @@
++/*
++ * Xen SCSI backend driver
++ *
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * Based on the blkback driver code.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <stdarg.h>
++#include <linux/module.h>
++#include <linux/kthread.h>
++#include <scsi/scsi.h>
++#include <scsi/scsi_host.h>
++#include <scsi/scsi_device.h>
++
++#include "common.h"
++
++struct backend_info
++{
++ struct xenbus_device *dev;
++ struct vscsibk_info *info;
++};
++
++
++static int __vscsiif_name(struct backend_info *be, char *buf)
++{
++ struct xenbus_device *dev = be->dev;
++ unsigned int domid, id;
++
++ sscanf(dev->nodename, "backend/vscsi/%u/%u", &domid, &id);
++ snprintf(buf, TASK_COMM_LEN, "vscsi.%u.%u", be->info->domid, id);
++
++ return 0;
++}
++
++static int scsiback_map(struct backend_info *be)
++{
++ struct xenbus_device *dev = be->dev;
++ unsigned long ring_ref;
++ unsigned int evtchn;
++ int err;
++ char name[TASK_COMM_LEN];
++
++ err = xenbus_gather(XBT_NIL, dev->otherend,
++ "ring-ref", "%lu", &ring_ref,
++ "event-channel", "%u", &evtchn, NULL);
++ if (err) {
++ xenbus_dev_fatal(dev, err, "reading %s ring", dev->otherend);
++ return err;
++ }
++
++ err = scsiback_init_sring(be->info, ring_ref, evtchn);
++ if (err)
++ return err;
++
++ err = __vscsiif_name(be, name);
++ if (err) {
++ xenbus_dev_error(dev, err, "get scsiback dev name");
++ return err;
++ }
++
++ be->info->kthread = kthread_run(scsiback_schedule, be->info, name);
++ if (IS_ERR(be->info->kthread)) {
++ err = PTR_ERR(be->info->kthread);
++ be->info->kthread = NULL;
++ xenbus_dev_error(be->dev, err, "start vscsiif");
++ return err;
++ }
++
++ return 0;
++}
++
++
++struct scsi_device *scsiback_get_scsi_device(struct ids_tuple *phy)
++{
++ struct Scsi_Host *shost;
++ struct scsi_device *sdev = NULL;
++
++ shost = scsi_host_lookup(phy->hst);
++ if (IS_ERR(shost)) {
++ printk(KERN_ERR "scsiback: host%d doesn't exist.\n",
++ phy->hst);
++ return NULL;
++ }
++ sdev = scsi_device_lookup(shost, phy->chn, phy->tgt, phy->lun);
++ if (!sdev) {
++ printk(KERN_ERR "scsiback: %d:%d:%d:%d doesn't exist.\n",
++ phy->hst, phy->chn, phy->tgt, phy->lun);
++ scsi_host_put(shost);
++ return NULL;
++ }
++
++ scsi_host_put(shost);
++ return (sdev);
++}
++
++#define VSCSIBACK_OP_ADD_OR_DEL_LUN 1
++#define VSCSIBACK_OP_UPDATEDEV_STATE 2
++
++
++static void scsiback_do_lun_hotplug(struct backend_info *be, int op)
++{
++ int i, err = 0;
++ struct ids_tuple phy, vir;
++ int device_state;
++ char str[64], state_str[64];
++ char **dir;
++ unsigned int dir_n = 0;
++ struct xenbus_device *dev = be->dev;
++ struct scsi_device *sdev;
++
++ dir = xenbus_directory(XBT_NIL, dev->nodename, "vscsi-devs", &dir_n);
++ if (IS_ERR(dir))
++ return;
++
++ for (i = 0; i < dir_n; i++) {
++
++ /* read status */
++ snprintf(state_str, sizeof(state_str), "vscsi-devs/%s/state", dir[i]);
++ err = xenbus_scanf(XBT_NIL, dev->nodename, state_str, "%u",
++ &device_state);
++ if (XENBUS_EXIST_ERR(err))
++ continue;
++
++ /* physical SCSI device */
++ snprintf(str, sizeof(str), "vscsi-devs/%s/p-dev", dir[i]);
++ err = xenbus_scanf(XBT_NIL, dev->nodename, str,
++ "%u:%u:%u:%u", &phy.hst, &phy.chn, &phy.tgt, &phy.lun);
++ if (XENBUS_EXIST_ERR(err)) {
++ xenbus_printf(XBT_NIL, dev->nodename, state_str,
++ "%d", XenbusStateClosed);
++ continue;
++ }
++
++ /* virtual SCSI device */
++ snprintf(str, sizeof(str), "vscsi-devs/%s/v-dev", dir[i]);
++ err = xenbus_scanf(XBT_NIL, dev->nodename, str,
++ "%u:%u:%u:%u", &vir.hst, &vir.chn, &vir.tgt, &vir.lun);
++ if (XENBUS_EXIST_ERR(err)) {
++ xenbus_printf(XBT_NIL, dev->nodename, state_str,
++ "%d", XenbusStateClosed);
++ continue;
++ }
++
++ switch (op) {
++ case VSCSIBACK_OP_ADD_OR_DEL_LUN:
++ if (device_state == XenbusStateInitialising) {
++ sdev = scsiback_get_scsi_device(&phy);
++ if (!sdev)
++ xenbus_printf(XBT_NIL, dev->nodename, state_str,
++ "%d", XenbusStateClosed);
++ else {
++ err = scsiback_add_translation_entry(be->info, sdev, &vir);
++ if (!err) {
++ if (xenbus_printf(XBT_NIL, dev->nodename, state_str,
++ "%d", XenbusStateInitialised)) {
++ printk(KERN_ERR "scsiback: xenbus_printf error %s\n", state_str);
++ scsiback_del_translation_entry(be->info, &vir);
++ }
++ } else {
++ scsi_device_put(sdev);
++ xenbus_printf(XBT_NIL, dev->nodename, state_str,
++ "%d", XenbusStateClosed);
++ }
++ }
++ }
++
++ if (device_state == XenbusStateClosing) {
++ if (!scsiback_del_translation_entry(be->info, &vir)) {
++ if (xenbus_printf(XBT_NIL, dev->nodename, state_str,
++ "%d", XenbusStateClosed))
++ printk(KERN_ERR "scsiback: xenbus_printf error %s\n", state_str);
++ }
++ }
++ break;
++
++ case VSCSIBACK_OP_UPDATEDEV_STATE:
++ if (device_state == XenbusStateInitialised) {
++ /* modify vscsi-devs/dev-x/state */
++ if (xenbus_printf(XBT_NIL, dev->nodename, state_str,
++ "%d", XenbusStateConnected)) {
++ printk(KERN_ERR "scsiback: xenbus_printf error %s\n", state_str);
++ scsiback_del_translation_entry(be->info, &vir);
++ xenbus_printf(XBT_NIL, dev->nodename, state_str,
++ "%d", XenbusStateClosed);
++ }
++ }
++ break;
++ /*When it is necessary, processing is added here.*/
++ default:
++ break;
++ }
++ }
++
++ kfree(dir);
++ return ;
++}
++
++
++static void scsiback_frontend_changed(struct xenbus_device *dev,
++ enum xenbus_state frontend_state)
++{
++ struct backend_info *be = dev->dev.driver_data;
++ int err;
++
++ switch (frontend_state) {
++ case XenbusStateInitialising:
++ break;
++ case XenbusStateInitialised:
++ err = scsiback_map(be);
++ if (err)
++ break;
++
++ scsiback_do_lun_hotplug(be, VSCSIBACK_OP_ADD_OR_DEL_LUN);
++ xenbus_switch_state(dev, XenbusStateConnected);
++
++ break;
++ case XenbusStateConnected:
++
++ scsiback_do_lun_hotplug(be, VSCSIBACK_OP_UPDATEDEV_STATE);
++
++ if (dev->state == XenbusStateConnected)
++ break;
++
++ xenbus_switch_state(dev, XenbusStateConnected);
++
++ break;
++
++ case XenbusStateClosing:
++ scsiback_disconnect(be->info);
++ xenbus_switch_state(dev, XenbusStateClosing);
++ break;
++
++ case XenbusStateClosed:
++ xenbus_switch_state(dev, XenbusStateClosed);
++ if (xenbus_dev_is_online(dev))
++ break;
++ /* fall through if not online */
++ case XenbusStateUnknown:
++ device_unregister(&dev->dev);
++ break;
++
++ case XenbusStateReconfiguring:
++ scsiback_do_lun_hotplug(be, VSCSIBACK_OP_ADD_OR_DEL_LUN);
++
++ xenbus_switch_state(dev, XenbusStateReconfigured);
++
++ break;
++
++ default:
++ xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
++ frontend_state);
++ break;
++ }
++}
++
++
++static int scsiback_remove(struct xenbus_device *dev)
++{
++ struct backend_info *be = dev->dev.driver_data;
++
++ if (be->info) {
++ scsiback_disconnect(be->info);
++ scsiback_release_translation_entry(be->info);
++ scsiback_free(be->info);
++ be->info = NULL;
++ }
++
++ kfree(be);
++ dev->dev.driver_data = NULL;
++
++ return 0;
++}
++
++
++static int scsiback_probe(struct xenbus_device *dev,
++ const struct xenbus_device_id *id)
++{
++ int err;
++
++ struct backend_info *be = kzalloc(sizeof(struct backend_info),
++ GFP_KERNEL);
++
++ DPRINTK("%p %d\n", dev, dev->otherend_id);
++
++ if (!be) {
++ xenbus_dev_fatal(dev, -ENOMEM,
++ "allocating backend structure");
++ return -ENOMEM;
++ }
++ be->dev = dev;
++ dev->dev.driver_data = be;
++
++ be->info = vscsibk_info_alloc(dev->otherend_id);
++ if (IS_ERR(be->info)) {
++ err = PTR_ERR(be->info);
++ be->info = NULL;
++ xenbus_dev_fatal(dev, err, "creating scsihost interface");
++ goto fail;
++ }
++
++ be->info->dev = dev;
++ be->info->irq = 0;
++
++ scsiback_init_translation_table(be->info);
++
++ err = xenbus_switch_state(dev, XenbusStateInitWait);
++ if (err)
++ goto fail;
++
++ return 0;
++
++
++fail:
++ printk(KERN_WARNING "scsiback: %s failed\n",__FUNCTION__);
++ scsiback_remove(dev);
++
++ return err;
++}
++
++
++static struct xenbus_device_id scsiback_ids[] = {
++ { "vscsi" },
++ { "" }
++};
++
++static struct xenbus_driver scsiback = {
++ .name = "vscsi",
++ .owner = THIS_MODULE,
++ .ids = scsiback_ids,
++ .probe = scsiback_probe,
++ .remove = scsiback_remove,
++ .otherend_changed = scsiback_frontend_changed
++};
++
++int scsiback_xenbus_init(void)
++{
++ return xenbus_register_backend(&scsiback);
++}
++
++void scsiback_xenbus_unregister(void)
++{
++ xenbus_unregister_driver(&scsiback);
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/scsifront/common.h linux-2.6.18-xen-3.3.0/drivers/xen/scsifront/common.h
+--- linux-2.6.18.8/drivers/xen/scsifront/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsifront/common.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,129 @@
++/*
++ * Xen SCSI frontend driver
++ *
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#ifndef __XEN_DRIVERS_SCSIFRONT_H__
++#define __XEN_DRIVERS_SCSIFRONT_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/kthread.h>
++#include <linux/wait.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/blkdev.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
++#include <scsi/scsi.h>
++#include <scsi/scsi_host.h>
++#include <xen/xenbus.h>
++#include <xen/gnttab.h>
++#include <xen/evtchn.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/io/ring.h>
++#include <xen/interface/io/vscsiif.h>
++#include <asm/delay.h>
++
++
++#define GRANT_INVALID_REF 0
++#define VSCSI_IN_ABORT 1
++#define VSCSI_IN_RESET 2
++
++/* tuning point*/
++#define VSCSIIF_DEFAULT_CMD_PER_LUN 10
++#define VSCSIIF_MAX_TARGET 64
++#define VSCSIIF_MAX_LUN 255
++
++#define VSCSIIF_RING_SIZE \
++ __RING_SIZE((struct vscsiif_sring *)0, PAGE_SIZE)
++#define VSCSIIF_MAX_REQS VSCSIIF_RING_SIZE
++
++struct vscsifrnt_shadow {
++ uint16_t next_free;
++
++ /* command between backend and frontend
++ * VSCSIIF_ACT_SCSI_CDB or VSCSIIF_ACT_SCSI_RESET */
++ unsigned char act;
++
++ /* do reset function */
++ wait_queue_head_t wq_reset; /* reset work queue */
++ int wait_reset; /* reset work queue condition */
++ int32_t rslt_reset; /* reset response status */
++ /* (SUCESS or FAILED) */
++
++ /* for DMA_TO_DEVICE(1), DMA_FROM_DEVICE(2), DMA_NONE(3)
++ requests */
++ unsigned int sc_data_direction;
++
++ /* Number of pieces of scatter-gather */
++ unsigned int nr_segments;
++
++ /* requested struct scsi_cmnd is stored from kernel */
++ unsigned long req_scsi_cmnd;
++ int gref[VSCSIIF_SG_TABLESIZE];
++};
++
++struct vscsifrnt_info {
++ struct xenbus_device *dev;
++
++ struct Scsi_Host *host;
++
++ spinlock_t io_lock;
++ spinlock_t shadow_lock;
++ unsigned int evtchn;
++ unsigned int irq;
++
++ grant_ref_t ring_ref;
++ struct vscsiif_front_ring ring;
++ struct vscsiif_response ring_res;
++
++ struct vscsifrnt_shadow shadow[VSCSIIF_MAX_REQS];
++ uint32_t shadow_free;
++
++ struct task_struct *kthread;
++ wait_queue_head_t wq;
++ unsigned int waiting_resp;
++
++};
++
++#define DPRINTK(_f, _a...) \
++ pr_debug("(file=%s, line=%d) " _f, \
++ __FILE__ , __LINE__ , ## _a )
++
++int scsifront_xenbus_init(void);
++void scsifront_xenbus_unregister(void);
++int scsifront_schedule(void *data);
++irqreturn_t scsifront_intr(int irq, void *dev_id, struct pt_regs *ptregs);
++int scsifront_cmd_done(struct vscsifrnt_info *info);
++
++
++#endif /* __XEN_DRIVERS_SCSIFRONT_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/scsifront/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/scsifront/Makefile
+--- linux-2.6.18.8/drivers/xen/scsifront/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsifront/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,3 @@
++
++obj-$(CONFIG_XEN_SCSI_FRONTEND) := xenscsi.o
++xenscsi-objs := scsifront.o xenbus.o
+diff -rpuN linux-2.6.18.8/drivers/xen/scsifront/scsifront.c linux-2.6.18-xen-3.3.0/drivers/xen/scsifront/scsifront.c
+--- linux-2.6.18.8/drivers/xen/scsifront/scsifront.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsifront/scsifront.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,511 @@
++/*
++ * Xen SCSI frontend driver
++ *
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++
++#include <linux/version.h>
++#include "common.h"
++
++static int get_id_from_freelist(struct vscsifrnt_info *info)
++{
++ unsigned long flags;
++ uint32_t free;
++
++ spin_lock_irqsave(&info->shadow_lock, flags);
++
++ free = info->shadow_free;
++ BUG_ON(free > VSCSIIF_MAX_REQS);
++ info->shadow_free = info->shadow[free].next_free;
++ info->shadow[free].next_free = 0x0fff;
++
++ info->shadow[free].wait_reset = 0;
++
++ spin_unlock_irqrestore(&info->shadow_lock, flags);
++
++ return free;
++}
++
++static void add_id_to_freelist(struct vscsifrnt_info *info, uint32_t id)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&info->shadow_lock, flags);
++
++ info->shadow[id].next_free = info->shadow_free;
++ info->shadow[id].req_scsi_cmnd = 0;
++ info->shadow_free = id;
++
++ spin_unlock_irqrestore(&info->shadow_lock, flags);
++}
++
++
++struct vscsiif_request * scsifront_pre_request(struct vscsifrnt_info *info)
++{
++ struct vscsiif_front_ring *ring = &(info->ring);
++ vscsiif_request_t *ring_req;
++ uint32_t id;
++
++ ring_req = RING_GET_REQUEST(&(info->ring), ring->req_prod_pvt);
++
++ ring->req_prod_pvt++;
++
++ id = get_id_from_freelist(info); /* use id by response */
++ ring_req->rqid = (uint16_t)id;
++
++ return ring_req;
++}
++
++
++static void scsifront_notify_work(struct vscsifrnt_info *info)
++{
++ info->waiting_resp = 1;
++ wake_up(&info->wq);
++}
++
++
++static void scsifront_do_request(struct vscsifrnt_info *info)
++{
++ struct vscsiif_front_ring *ring = &(info->ring);
++ unsigned int irq = info->irq;
++ int notify;
++
++ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(ring, notify);
++ if (notify)
++ notify_remote_via_irq(irq);
++}
++
++irqreturn_t scsifront_intr(int irq, void *dev_id, struct pt_regs *ptregs)
++{
++ scsifront_notify_work((struct vscsifrnt_info *)dev_id);
++ return IRQ_HANDLED;
++}
++
++
++static void scsifront_gnttab_done(struct vscsifrnt_shadow *s, uint32_t id)
++{
++ int i;
++
++ if (s->sc_data_direction == DMA_NONE)
++ return;
++
++ if (s->nr_segments) {
++ for (i = 0; i < s->nr_segments; i++) {
++ if (unlikely(gnttab_query_foreign_access(
++ s->gref[i]) != 0)) {
++ printk(KERN_ALERT "scsifront: "
++ "grant still in use by backend.\n");
++ BUG();
++ }
++ gnttab_end_foreign_access(s->gref[i], 0UL);
++ }
++ }
++
++ return;
++}
++
++
++static void scsifront_cdb_cmd_done(struct vscsifrnt_info *info,
++ vscsiif_response_t *ring_res)
++{
++ struct scsi_cmnd *sc;
++ uint32_t id;
++ uint8_t sense_len;
++
++ id = ring_res->rqid;
++ sc = (struct scsi_cmnd *)info->shadow[id].req_scsi_cmnd;
++
++ if (sc == NULL)
++ BUG();
++
++ scsifront_gnttab_done(&info->shadow[id], id);
++ add_id_to_freelist(info, id);
++
++ sc->result = ring_res->rslt;
++ sc->resid = ring_res->residual_len;
++
++ if (ring_res->sense_len > VSCSIIF_SENSE_BUFFERSIZE)
++ sense_len = VSCSIIF_SENSE_BUFFERSIZE;
++ else
++ sense_len = ring_res->sense_len;
++
++ if (sense_len)
++ memcpy(sc->sense_buffer, ring_res->sense_buffer, sense_len);
++
++ sc->scsi_done(sc);
++
++ return;
++}
++
++
++static void scsifront_sync_cmd_done(struct vscsifrnt_info *info,
++ vscsiif_response_t *ring_res)
++{
++ uint16_t id = ring_res->rqid;
++ unsigned long flags;
++
++ spin_lock_irqsave(&info->shadow_lock, flags);
++ info->shadow[id].wait_reset = 1;
++ info->shadow[id].rslt_reset = ring_res->rslt;
++ spin_unlock_irqrestore(&info->shadow_lock, flags);
++
++ wake_up(&(info->shadow[id].wq_reset));
++}
++
++
++int scsifront_cmd_done(struct vscsifrnt_info *info)
++{
++ vscsiif_response_t *ring_res;
++
++ RING_IDX i, rp;
++ int more_to_do = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&info->io_lock, flags);
++
++ rp = info->ring.sring->rsp_prod;
++ rmb();
++ for (i = info->ring.rsp_cons; i != rp; i++) {
++
++ ring_res = RING_GET_RESPONSE(&info->ring, i);
++
++ if (info->shadow[ring_res->rqid].act == VSCSIIF_ACT_SCSI_CDB)
++ scsifront_cdb_cmd_done(info, ring_res);
++ else
++ scsifront_sync_cmd_done(info, ring_res);
++ }
++
++ info->ring.rsp_cons = i;
++
++ if (i != info->ring.req_prod_pvt) {
++ RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do);
++ } else {
++ info->ring.sring->rsp_event = i + 1;
++ }
++
++ spin_unlock_irqrestore(&info->io_lock, flags);
++
++
++ /* Yield point for this unbounded loop. */
++ cond_resched();
++
++ return more_to_do;
++}
++
++
++
++
++int scsifront_schedule(void *data)
++{
++ struct vscsifrnt_info *info = (struct vscsifrnt_info *)data;
++
++ while (!kthread_should_stop()) {
++ wait_event_interruptible(
++ info->wq,
++ info->waiting_resp || kthread_should_stop());
++
++ info->waiting_resp = 0;
++ smp_mb();
++
++ if (scsifront_cmd_done(info))
++ info->waiting_resp = 1;
++ }
++
++ return 0;
++}
++
++
++
++static int map_data_for_request(struct vscsifrnt_info *info,
++ struct scsi_cmnd *sc, vscsiif_request_t *ring_req, uint32_t id)
++{
++ grant_ref_t gref_head;
++ struct page *page;
++ int err, i, ref, ref_cnt = 0;
++ int write = (sc->sc_data_direction == DMA_TO_DEVICE);
++ int nr_pages, off, len, bytes;
++ unsigned long buffer_pfn;
++ unsigned int data_len = 0;
++
++ if (sc->sc_data_direction == DMA_NONE)
++ return 0;
++
++ err = gnttab_alloc_grant_references(VSCSIIF_SG_TABLESIZE, &gref_head);
++ if (err) {
++ printk(KERN_ERR "scsifront: gnttab_alloc_grant_references() error\n");
++ return -ENOMEM;
++ }
++
++ if (sc->use_sg) {
++ /* quoted scsi_lib.c/scsi_req_map_sg . */
++ struct scatterlist *sg = (struct scatterlist *)sc->request_buffer;
++ nr_pages = (sc->request_bufflen + sg[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++ if (nr_pages > VSCSIIF_SG_TABLESIZE) {
++ printk(KERN_ERR "scsifront: Unable to map request_buffer for command!\n");
++ ref_cnt = (-E2BIG);
++ goto big_to_sg;
++ }
++
++ for (i = 0; i < sc->use_sg; i++) {
++ page = sg[i].page;
++ off = sg[i].offset;
++ len = sg[i].length;
++ data_len += len;
++
++ buffer_pfn = page_to_phys(page) >> PAGE_SHIFT;
++
++ while (len > 0) {
++ bytes = min_t(unsigned int, len, PAGE_SIZE - off);
++
++ ref = gnttab_claim_grant_reference(&gref_head);
++ BUG_ON(ref == -ENOSPC);
++
++ gnttab_grant_foreign_access_ref(ref, info->dev->otherend_id,
++ buffer_pfn, write);
++
++ info->shadow[id].gref[ref_cnt] = ref;
++ ring_req->seg[ref_cnt].gref = ref;
++ ring_req->seg[ref_cnt].offset = (uint16_t)off;
++ ring_req->seg[ref_cnt].length = (uint16_t)bytes;
++
++ buffer_pfn++;
++ len -= bytes;
++ off = 0;
++ ref_cnt++;
++ }
++ }
++ } else if (sc->request_bufflen) {
++ unsigned long end = ((unsigned long)sc->request_buffer
++ + sc->request_bufflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ unsigned long start = (unsigned long)sc->request_buffer >> PAGE_SHIFT;
++
++ page = virt_to_page(sc->request_buffer);
++ nr_pages = end - start;
++ len = sc->request_bufflen;
++
++ if (nr_pages > VSCSIIF_SG_TABLESIZE) {
++ ref_cnt = (-E2BIG);
++ goto big_to_sg;
++ }
++
++ buffer_pfn = page_to_phys(page) >> PAGE_SHIFT;
++
++ off = offset_in_page((unsigned long)sc->request_buffer);
++ for (i = 0; i < nr_pages; i++) {
++ bytes = PAGE_SIZE - off;
++
++ if (bytes > len)
++ bytes = len;
++
++ ref = gnttab_claim_grant_reference(&gref_head);
++ BUG_ON(ref == -ENOSPC);
++
++ gnttab_grant_foreign_access_ref(ref, info->dev->otherend_id,
++ buffer_pfn, write);
++
++ info->shadow[id].gref[i] = ref;
++ ring_req->seg[i].gref = ref;
++ ring_req->seg[i].offset = (uint16_t)off;
++ ring_req->seg[i].length = (uint16_t)bytes;
++
++ buffer_pfn++;
++ len -= bytes;
++ off = 0;
++ ref_cnt++;
++ }
++ }
++
++big_to_sg:
++
++ gnttab_free_grant_references(gref_head);
++
++ return ref_cnt;
++}
++
++static int scsifront_queuecommand(struct scsi_cmnd *sc,
++ void (*done)(struct scsi_cmnd *))
++{
++ struct vscsifrnt_info *info =
++ (struct vscsifrnt_info *) sc->device->host->hostdata;
++ vscsiif_request_t *ring_req;
++ int ref_cnt;
++ uint16_t rqid;
++
++ if (RING_FULL(&info->ring)) {
++ goto out_host_busy;
++ }
++
++ sc->scsi_done = done;
++ sc->result = 0;
++
++ ring_req = scsifront_pre_request(info);
++ rqid = ring_req->rqid;
++ ring_req->act = VSCSIIF_ACT_SCSI_CDB;
++
++ ring_req->id = sc->device->id;
++ ring_req->lun = sc->device->lun;
++ ring_req->channel = sc->device->channel;
++ ring_req->cmd_len = sc->cmd_len;
++
++ BUG_ON(sc->cmd_len > VSCSIIF_MAX_COMMAND_SIZE);
++
++ if ( sc->cmd_len )
++ memcpy(ring_req->cmnd, sc->cmnd, sc->cmd_len);
++ else
++ memset(ring_req->cmnd, 0, VSCSIIF_MAX_COMMAND_SIZE);
++
++ ring_req->sc_data_direction = (uint8_t)sc->sc_data_direction;
++ ring_req->timeout_per_command = (sc->timeout_per_command / HZ);
++
++ info->shadow[rqid].req_scsi_cmnd = (unsigned long)sc;
++ info->shadow[rqid].sc_data_direction = sc->sc_data_direction;
++ info->shadow[rqid].act = ring_req->act;
++
++ ref_cnt = map_data_for_request(info, sc, ring_req, rqid);
++ if (ref_cnt < 0) {
++ add_id_to_freelist(info, rqid);
++ if (ref_cnt == (-ENOMEM))
++ goto out_host_busy;
++ else {
++ sc->result = (DID_ERROR << 16);
++ goto out_fail_command;
++ }
++ }
++
++ ring_req->nr_segments = (uint8_t)ref_cnt;
++ info->shadow[rqid].nr_segments = ref_cnt;
++
++ scsifront_do_request(info);
++
++ return 0;
++
++out_host_busy:
++ return SCSI_MLQUEUE_HOST_BUSY;
++
++out_fail_command:
++ done(sc);
++ return 0;
++}
++
++
++static int scsifront_eh_abort_handler(struct scsi_cmnd *sc)
++{
++ return (FAILED);
++}
++
++/* vscsi supports only device_reset, because it is each of LUNs */
++static int scsifront_dev_reset_handler(struct scsi_cmnd *sc)
++{
++ struct Scsi_Host *host = sc->device->host;
++ struct vscsifrnt_info *info =
++ (struct vscsifrnt_info *) sc->device->host->hostdata;
++
++ vscsiif_request_t *ring_req;
++ uint16_t rqid;
++ int err;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
++ spin_lock_irq(host->host_lock);
++#endif
++
++ ring_req = scsifront_pre_request(info);
++ ring_req->act = VSCSIIF_ACT_SCSI_RESET;
++
++ rqid = ring_req->rqid;
++ info->shadow[rqid].act = VSCSIIF_ACT_SCSI_RESET;
++
++ ring_req->channel = sc->device->channel;
++ ring_req->id = sc->device->id;
++ ring_req->lun = sc->device->lun;
++ ring_req->cmd_len = sc->cmd_len;
++
++ if ( sc->cmd_len )
++ memcpy(ring_req->cmnd, sc->cmnd, sc->cmd_len);
++ else
++ memset(ring_req->cmnd, 0, VSCSIIF_MAX_COMMAND_SIZE);
++
++ ring_req->sc_data_direction = (uint8_t)sc->sc_data_direction;
++ ring_req->timeout_per_command = (sc->timeout_per_command / HZ);
++ ring_req->nr_segments = 0;
++
++ scsifront_do_request(info);
++
++ spin_unlock_irq(host->host_lock);
++ wait_event_interruptible(info->shadow[rqid].wq_reset,
++ info->shadow[rqid].wait_reset);
++ spin_lock_irq(host->host_lock);
++
++ err = info->shadow[rqid].rslt_reset;
++
++ add_id_to_freelist(info, rqid);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
++ spin_unlock_irq(host->host_lock);
++#endif
++ return (err);
++}
++
++
++struct scsi_host_template scsifront_sht = {
++ .module = THIS_MODULE,
++ .name = "Xen SCSI frontend driver",
++ .queuecommand = scsifront_queuecommand,
++ .eh_abort_handler = scsifront_eh_abort_handler,
++ .eh_device_reset_handler= scsifront_dev_reset_handler,
++ .cmd_per_lun = VSCSIIF_DEFAULT_CMD_PER_LUN,
++ .can_queue = VSCSIIF_MAX_REQS,
++ .this_id = -1,
++ .sg_tablesize = VSCSIIF_SG_TABLESIZE,
++ .use_clustering = DISABLE_CLUSTERING,
++ .proc_name = "scsifront",
++};
++
++
++static int __init scsifront_init(void)
++{
++ int err;
++
++ if (!is_running_on_xen())
++ return -ENODEV;
++
++ err = scsifront_xenbus_init();
++
++ return err;
++}
++
++static void __exit scsifront_exit(void)
++{
++ scsifront_xenbus_unregister();
++}
++
++module_init(scsifront_init);
++module_exit(scsifront_exit);
++
++MODULE_DESCRIPTION("Xen SCSI frontend driver");
++MODULE_LICENSE("GPL");
+diff -rpuN linux-2.6.18.8/drivers/xen/scsifront/xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/scsifront/xenbus.c
+--- linux-2.6.18.8/drivers/xen/scsifront/xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/scsifront/xenbus.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,421 @@
++/*
++ * Xen SCSI frontend driver
++ *
++ * Copyright (c) 2008, FUJITSU Limited
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++
++#include <linux/version.h>
++#include "common.h"
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
++ #define DEFAULT_TASK_COMM_LEN 16
++#else
++ #define DEFAULT_TASK_COMM_LEN TASK_COMM_LEN
++#endif
++
++extern struct scsi_host_template scsifront_sht;
++
++static void scsifront_free(struct vscsifrnt_info *info)
++{
++ struct Scsi_Host *host = info->host;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
++ if (host->shost_state != SHOST_DEL) {
++#else
++ if (!test_bit(SHOST_DEL, &host->shost_state)) {
++#endif
++ scsi_remove_host(info->host);
++ }
++
++ if (info->ring_ref != GRANT_INVALID_REF) {
++ gnttab_end_foreign_access(info->ring_ref,
++ (unsigned long)info->ring.sring);
++ info->ring_ref = GRANT_INVALID_REF;
++ info->ring.sring = NULL;
++ }
++
++ if (info->irq)
++ unbind_from_irqhandler(info->irq, info);
++ info->irq = 0;
++
++ scsi_host_put(info->host);
++}
++
++
++static int scsifront_alloc_ring(struct vscsifrnt_info *info)
++{
++ struct xenbus_device *dev = info->dev;
++ struct vscsiif_sring *sring;
++ int err = -ENOMEM;
++
++
++ info->ring_ref = GRANT_INVALID_REF;
++
++ /***** Frontend to Backend ring start *****/
++ sring = (struct vscsiif_sring *) __get_free_page(GFP_KERNEL);
++ if (!sring) {
++ xenbus_dev_fatal(dev, err, "fail to allocate shared ring (Front to Back)");
++ return err;
++ }
++ SHARED_RING_INIT(sring);
++ FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
++
++ err = xenbus_grant_ring(dev, virt_to_mfn(sring));
++ if (err < 0) {
++ free_page((unsigned long) sring);
++ info->ring.sring = NULL;
++ xenbus_dev_fatal(dev, err, "fail to grant shared ring (Front to Back)");
++ goto free_sring;
++ }
++ info->ring_ref = err;
++
++ err = bind_listening_port_to_irqhandler(
++ dev->otherend_id, scsifront_intr,
++ SA_SAMPLE_RANDOM, "scsifront", info);
++
++ if (err <= 0) {
++ xenbus_dev_fatal(dev, err, "bind_listening_port_to_irqhandler");
++ goto free_sring;
++ }
++ info->irq = err;
++
++ return 0;
++
++/* free resource */
++free_sring:
++ scsifront_free(info);
++
++ return err;
++}
++
++
++static int scsifront_init_ring(struct vscsifrnt_info *info)
++{
++ struct xenbus_device *dev = info->dev;
++ struct xenbus_transaction xbt;
++ int err;
++
++ DPRINTK("%s\n",__FUNCTION__);
++
++ err = scsifront_alloc_ring(info);
++ if (err)
++ return err;
++ DPRINTK("%u %u\n", info->ring_ref, info->evtchn);
++
++again:
++ err = xenbus_transaction_start(&xbt);
++ if (err) {
++ xenbus_dev_fatal(dev, err, "starting transaction");
++ }
++
++ err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u",
++ info->ring_ref);
++ if (err) {
++ xenbus_dev_fatal(dev, err, "%s", "writing ring-ref");
++ goto fail;
++ }
++
++ err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++ irq_to_evtchn_port(info->irq));
++
++ if (err) {
++ xenbus_dev_fatal(dev, err, "%s", "writing event-channel");
++ goto fail;
++ }
++
++ err = xenbus_transaction_end(xbt, 0);
++ if (err) {
++ if (err == -EAGAIN)
++ goto again;
++ xenbus_dev_fatal(dev, err, "completing transaction");
++ goto free_sring;
++ }
++
++ return 0;
++
++fail:
++ xenbus_transaction_end(xbt, 1);
++free_sring:
++ /* free resource */
++ scsifront_free(info);
++
++ return err;
++}
++
++
++static int scsifront_probe(struct xenbus_device *dev,
++ const struct xenbus_device_id *id)
++{
++ struct vscsifrnt_info *info;
++ struct Scsi_Host *host;
++ int i, err = -ENOMEM;
++ char name[DEFAULT_TASK_COMM_LEN];
++
++ host = scsi_host_alloc(&scsifront_sht, sizeof(*info));
++ if (!host) {
++ xenbus_dev_fatal(dev, err, "fail to allocate scsi host");
++ return err;
++ }
++ info = (struct vscsifrnt_info *) host->hostdata;
++ info->host = host;
++
++
++ dev->dev.driver_data = info;
++ info->dev = dev;
++
++ for (i = 0; i < VSCSIIF_MAX_REQS; i++) {
++ info->shadow[i].next_free = i + 1;
++ init_waitqueue_head(&(info->shadow[i].wq_reset));
++ info->shadow[i].wait_reset = 0;
++ }
++ info->shadow[VSCSIIF_MAX_REQS - 1].next_free = 0x0fff;
++
++ err = scsifront_init_ring(info);
++ if (err) {
++ scsi_host_put(host);
++ return err;
++ }
++
++ init_waitqueue_head(&info->wq);
++ spin_lock_init(&info->io_lock);
++ spin_lock_init(&info->shadow_lock);
++
++ snprintf(name, DEFAULT_TASK_COMM_LEN, "vscsiif.%d", info->host->host_no);
++
++ info->kthread = kthread_run(scsifront_schedule, info, name);
++ if (IS_ERR(info->kthread)) {
++ err = PTR_ERR(info->kthread);
++ info->kthread = NULL;
++ printk(KERN_ERR "scsifront: kthread start err %d\n", err);
++ goto free_sring;
++ }
++
++ host->max_id = VSCSIIF_MAX_TARGET;
++ host->max_channel = 0;
++ host->max_lun = VSCSIIF_MAX_LUN;
++ host->max_sectors = (VSCSIIF_SG_TABLESIZE - 1) * PAGE_SIZE / 512;
++
++ err = scsi_add_host(host, &dev->dev);
++ if (err) {
++ printk(KERN_ERR "scsifront: fail to add scsi host %d\n", err);
++ goto free_sring;
++ }
++
++ xenbus_switch_state(dev, XenbusStateInitialised);
++
++ return 0;
++
++free_sring:
++ /* free resource */
++ scsifront_free(info);
++ return err;
++}
++
++static int scsifront_remove(struct xenbus_device *dev)
++{
++ struct vscsifrnt_info *info = dev->dev.driver_data;
++
++ DPRINTK("%s: %s removed\n",__FUNCTION__ ,dev->nodename);
++
++ if (info->kthread) {
++ kthread_stop(info->kthread);
++ info->kthread = NULL;
++ }
++
++ scsifront_free(info);
++
++ return 0;
++}
++
++
++static int scsifront_disconnect(struct vscsifrnt_info *info)
++{
++ struct xenbus_device *dev = info->dev;
++ struct Scsi_Host *host = info->host;
++
++ DPRINTK("%s: %s disconnect\n",__FUNCTION__ ,dev->nodename);
++
++ /*
++ When this function is executed, all devices of
++ Frontend have been deleted.
++ Therefore, it need not block I/O before remove_host.
++ */
++
++ scsi_remove_host(host);
++ xenbus_frontend_closed(dev);
++
++ return 0;
++}
++
++#define VSCSIFRONT_OP_ADD_LUN 1
++#define VSCSIFRONT_OP_DEL_LUN 2
++
++static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op)
++{
++ struct xenbus_device *dev = info->dev;
++ int i, err = 0;
++ char str[64], state_str[64];
++ char **dir;
++ unsigned int dir_n = 0;
++ unsigned int device_state;
++ unsigned int hst, chn, tgt, lun;
++ struct scsi_device *sdev;
++
++ dir = xenbus_directory(XBT_NIL, dev->otherend, "vscsi-devs", &dir_n);
++ if (IS_ERR(dir))
++ return;
++
++ for (i = 0; i < dir_n; i++) {
++ /* read status */
++ snprintf(str, sizeof(str), "vscsi-devs/%s/state", dir[i]);
++ err = xenbus_scanf(XBT_NIL, dev->otherend, str, "%u",
++ &device_state);
++ if (XENBUS_EXIST_ERR(err))
++ continue;
++
++ /* virtual SCSI device */
++ snprintf(str, sizeof(str), "vscsi-devs/%s/v-dev", dir[i]);
++ err = xenbus_scanf(XBT_NIL, dev->otherend, str,
++ "%u:%u:%u:%u", &hst, &chn, &tgt, &lun);
++ if (XENBUS_EXIST_ERR(err))
++ continue;
++
++ /* front device state path */
++ snprintf(state_str, sizeof(state_str), "vscsi-devs/%s/state", dir[i]);
++
++ switch (op) {
++ case VSCSIFRONT_OP_ADD_LUN:
++ if (device_state == XenbusStateInitialised) {
++ sdev = scsi_device_lookup(info->host, chn, tgt, lun);
++ if (sdev) {
++ printk(KERN_ERR "scsifront: Device already in use.\n");
++ scsi_device_put(sdev);
++ xenbus_printf(XBT_NIL, dev->nodename,
++ state_str, "%d", XenbusStateClosed);
++ } else {
++ scsi_add_device(info->host, chn, tgt, lun);
++ xenbus_printf(XBT_NIL, dev->nodename,
++ state_str, "%d", XenbusStateConnected);
++ }
++ }
++ break;
++ case VSCSIFRONT_OP_DEL_LUN:
++ if (device_state == XenbusStateClosing) {
++ sdev = scsi_device_lookup(info->host, chn, tgt, lun);
++ if (sdev) {
++ scsi_remove_device(sdev);
++ scsi_device_put(sdev);
++ xenbus_printf(XBT_NIL, dev->nodename,
++ state_str, "%d", XenbusStateClosed);
++ }
++ }
++ break;
++ default:
++ break;
++ }
++ }
++
++ kfree(dir);
++ return;
++}
++
++
++
++
++static void scsifront_backend_changed(struct xenbus_device *dev,
++ enum xenbus_state backend_state)
++{
++ struct vscsifrnt_info *info = dev->dev.driver_data;
++
++ DPRINTK("%p %u %u\n", dev, dev->state, backend_state);
++
++ switch (backend_state) {
++ case XenbusStateUnknown:
++ case XenbusStateInitialising:
++ case XenbusStateInitWait:
++ case XenbusStateClosed:
++ break;
++
++ case XenbusStateInitialised:
++ break;
++
++ case XenbusStateConnected:
++ if (xenbus_read_driver_state(dev->nodename) ==
++ XenbusStateInitialised) {
++ scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
++ }
++
++ if (dev->state == XenbusStateConnected)
++ break;
++
++ xenbus_switch_state(dev, XenbusStateConnected);
++ break;
++
++ case XenbusStateClosing:
++ scsifront_disconnect(info);
++ break;
++
++ case XenbusStateReconfiguring:
++ scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_DEL_LUN);
++ xenbus_switch_state(dev, XenbusStateReconfiguring);
++ break;
++
++ case XenbusStateReconfigured:
++ scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
++ xenbus_switch_state(dev, XenbusStateConnected);
++ break;
++ }
++}
++
++
++static struct xenbus_device_id scsifront_ids[] = {
++ { "vscsi" },
++ { "" }
++};
++
++
++static struct xenbus_driver scsifront_driver = {
++ .name = "vscsi",
++ .owner = THIS_MODULE,
++ .ids = scsifront_ids,
++ .probe = scsifront_probe,
++ .remove = scsifront_remove,
++/* .resume = scsifront_resume, */
++ .otherend_changed = scsifront_backend_changed,
++};
++
++int scsifront_xenbus_init(void)
++{
++ return xenbus_register_frontend(&scsifront_driver);
++}
++
++void scsifront_xenbus_unregister(void)
++{
++ xenbus_unregister_driver(&scsifront_driver);
++}
++
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/accel.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel.c
+--- linux-2.6.18.8/drivers/xen/sfc_netback/accel.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,129 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "accel.h"
++#include "accel_msg_iface.h"
++#include "accel_solarflare.h"
++
++#include <linux/notifier.h>
++
++#ifdef EFX_GCOV
++#include "gcov.h"
++#endif
++
++static int netback_accel_netdev_event(struct notifier_block *nb,
++ unsigned long event, void *ptr)
++{
++ struct net_device *net_dev = (struct net_device *)ptr;
++ struct netback_accel *bend;
++
++ if ((event == NETDEV_UP) || (event == NETDEV_DOWN)) {
++ mutex_lock(&bend_list_mutex);
++ bend = bend_list;
++ while (bend != NULL) {
++ mutex_lock(&bend->bend_mutex);
++ /*
++ * This happens when the shared pages have
++ * been unmapped, but the bend not yet removed
++ * from list
++ */
++ if (bend->shared_page == NULL)
++ goto next;
++
++ if (bend->net_dev->ifindex == net_dev->ifindex)
++ netback_accel_set_interface_state
++ (bend, event == NETDEV_UP);
++
++ next:
++ mutex_unlock(&bend->bend_mutex);
++ bend = bend->next_bend;
++ }
++ mutex_unlock(&bend_list_mutex);
++ }
++
++ return NOTIFY_DONE;
++}
++
++
++static struct notifier_block netback_accel_netdev_notifier = {
++ .notifier_call = netback_accel_netdev_event,
++};
++
++
++unsigned sfc_netback_max_pages = NETBACK_ACCEL_DEFAULT_MAX_BUF_PAGES;
++module_param_named(max_pages, sfc_netback_max_pages, uint, 0644);
++MODULE_PARM_DESC(max_pages,
++ "The number of buffer pages to enforce on each guest");
++
++/* Initialise subsystems need for the accelerated fast path */
++static int __init netback_accel_init(void)
++{
++ int rc = 0;
++
++#ifdef EFX_GCOV
++ gcov_provider_init(THIS_MODULE);
++#endif
++
++ rc = netback_accel_init_fwd();
++
++ if (rc == 0)
++ netback_accel_debugfs_init();
++
++ if (rc == 0)
++ rc = netback_accel_sf_init();
++
++ if (rc == 0)
++ rc = register_netdevice_notifier
++ (&netback_accel_netdev_notifier);
++
++ /*
++ * What if no device was found, shouldn't we clean up stuff
++ * we've allocated for acceleration subsystem?
++ */
++
++ return rc;
++}
++
++module_init(netback_accel_init);
++
++static void __exit netback_accel_exit(void)
++{
++ unregister_netdevice_notifier(&netback_accel_netdev_notifier);
++
++ netback_accel_sf_shutdown();
++
++ netback_accel_shutdown_bends();
++
++ netback_accel_debugfs_fini();
++
++ netback_accel_shutdown_fwd();
++
++#ifdef EFX_GCOV
++ gcov_provider_fini(THIS_MODULE);
++#endif
++}
++
++module_exit(netback_accel_exit);
++
++MODULE_LICENSE("GPL");
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/accel_debugfs.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_debugfs.c
+--- linux-2.6.18.8/drivers/xen/sfc_netback/accel_debugfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_debugfs.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,148 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/fs.h>
++#include <linux/debugfs.h>
++
++#include "accel.h"
++
++#if defined(CONFIG_DEBUG_FS)
++static struct dentry *sfc_debugfs_root = NULL;
++#endif
++
++#if NETBACK_ACCEL_STATS
++struct netback_accel_global_stats global_stats;
++#if defined(CONFIG_DEBUG_FS)
++static struct netback_accel_global_dbfs global_dbfs;
++#endif
++#endif
++
++void netback_accel_debugfs_init(void)
++{
++#if defined(CONFIG_DEBUG_FS)
++ sfc_debugfs_root = debugfs_create_dir("sfc_netback", NULL);
++ if (sfc_debugfs_root == NULL)
++ return;
++
++ global_dbfs.num_fwds = debugfs_create_u32
++ ("num_fwds", S_IRUSR | S_IRGRP | S_IROTH,
++ sfc_debugfs_root, &global_stats.num_fwds);
++ global_dbfs.dl_tx_packets = debugfs_create_u64
++ ("dl_tx_packets", S_IRUSR | S_IRGRP | S_IROTH,
++ sfc_debugfs_root, &global_stats.dl_tx_packets);
++ global_dbfs.dl_rx_packets = debugfs_create_u64
++ ("dl_rx_packets", S_IRUSR | S_IRGRP | S_IROTH,
++ sfc_debugfs_root, &global_stats.dl_rx_packets);
++ global_dbfs.dl_tx_bad_packets = debugfs_create_u64
++ ("dl_tx_bad_packets", S_IRUSR | S_IRGRP | S_IROTH,
++ sfc_debugfs_root, &global_stats.dl_tx_bad_packets);
++#endif
++}
++
++
++void netback_accel_debugfs_fini(void)
++{
++#if defined(CONFIG_DEBUG_FS)
++ debugfs_remove(global_dbfs.num_fwds);
++ debugfs_remove(global_dbfs.dl_tx_packets);
++ debugfs_remove(global_dbfs.dl_rx_packets);
++ debugfs_remove(global_dbfs.dl_tx_bad_packets);
++
++ debugfs_remove(sfc_debugfs_root);
++#endif
++}
++
++
++int netback_accel_debugfs_create(struct netback_accel *bend)
++{
++#if defined(CONFIG_DEBUG_FS)
++ /* Smallest length is 7 (vif0.0\n) */
++ int length = 7, temp;
++
++ if (sfc_debugfs_root == NULL)
++ return -ENOENT;
++
++ /* Work out length of string representation of far_end and vif_num */
++ temp = bend->far_end;
++ while (temp > 9) {
++ length++;
++ temp = temp / 10;
++ }
++ temp = bend->vif_num;
++ while (temp > 9) {
++ length++;
++ temp = temp / 10;
++ }
++
++ bend->dbfs_dir_name = kmalloc(length, GFP_KERNEL);
++ if (bend->dbfs_dir_name == NULL)
++ return -ENOMEM;
++ sprintf(bend->dbfs_dir_name, "vif%d.%d", bend->far_end, bend->vif_num);
++
++ bend->dbfs_dir = debugfs_create_dir(bend->dbfs_dir_name,
++ sfc_debugfs_root);
++ if (bend->dbfs_dir == NULL) {
++ kfree(bend->dbfs_dir_name);
++ return -ENOMEM;
++ }
++
++#if NETBACK_ACCEL_STATS
++ bend->dbfs.evq_wakeups = debugfs_create_u64
++ ("evq_wakeups", S_IRUSR | S_IRGRP | S_IROTH,
++ bend->dbfs_dir, &bend->stats.evq_wakeups);
++ bend->dbfs.evq_timeouts = debugfs_create_u64
++ ("evq_timeouts", S_IRUSR | S_IRGRP | S_IROTH,
++ bend->dbfs_dir, &bend->stats.evq_timeouts);
++ bend->dbfs.num_filters = debugfs_create_u32
++ ("num_filters", S_IRUSR | S_IRGRP | S_IROTH,
++ bend->dbfs_dir, &bend->stats.num_filters);
++ bend->dbfs.num_buffer_pages = debugfs_create_u32
++ ("num_buffer_pages", S_IRUSR | S_IRGRP | S_IROTH,
++ bend->dbfs_dir, &bend->stats.num_buffer_pages);
++#endif
++#endif
++ return 0;
++}
++
++
++int netback_accel_debugfs_remove(struct netback_accel *bend)
++{
++#if defined(CONFIG_DEBUG_FS)
++ if (bend->dbfs_dir != NULL) {
++#if NETBACK_ACCEL_STATS
++ debugfs_remove(bend->dbfs.evq_wakeups);
++ debugfs_remove(bend->dbfs.evq_timeouts);
++ debugfs_remove(bend->dbfs.num_filters);
++ debugfs_remove(bend->dbfs.num_buffer_pages);
++#endif
++ debugfs_remove(bend->dbfs_dir);
++ }
++
++ if (bend->dbfs_dir_name)
++ kfree(bend->dbfs_dir_name);
++#endif
++ return 0;
++}
++
++
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/accel_fwd.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_fwd.c
+--- linux-2.6.18.8/drivers/xen/sfc_netback/accel_fwd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_fwd.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,420 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "accel.h"
++#include "accel_cuckoo_hash.h"
++#include "accel_util.h"
++#include "accel_solarflare.h"
++
++#include "driverlink_api.h"
++
++#include <linux/if_arp.h>
++#include <linux/skbuff.h>
++#include <linux/list.h>
++
++/* State stored in the forward table */
++struct fwd_struct {
++ struct list_head link; /* Forms list */
++ void * context;
++ __u8 valid;
++ __u8 mac[ETH_ALEN];
++};
++
++/* Max value we support */
++#define NUM_FWDS_BITS 8
++#define NUM_FWDS (1 << NUM_FWDS_BITS)
++#define FWD_MASK (NUM_FWDS - 1)
++
++struct port_fwd {
++ /* Make a list */
++ struct list_head link;
++ /* Hash table to store the fwd_structs */
++ cuckoo_hash_table fwd_hash_table;
++ /* The array of fwd_structs */
++ struct fwd_struct *fwd_array;
++ /* Linked list of entries in use. */
++ struct list_head fwd_list;
++ /* Could do something clever with a reader/writer lock. */
++ spinlock_t fwd_lock;
++ /* Make find_free_entry() a bit faster by caching this */
++ int last_free_index;
++};
++
++/*
++ * This is unlocked as it's only called from dl probe and remove,
++ * which are themselves synchronised. Could get rid of it entirely as
++ * it's never iterated, but useful for debug
++ */
++static struct list_head port_fwds;
++
++
++/* Search the fwd_array for an unused entry */
++static int fwd_find_free_entry(struct port_fwd *fwd_set)
++{
++ int index = fwd_set->last_free_index;
++
++ do {
++ if (!fwd_set->fwd_array[index].valid) {
++ fwd_set->last_free_index = index;
++ return index;
++ }
++ index++;
++ if (index >= NUM_FWDS)
++ index = 0;
++ } while (index != fwd_set->last_free_index);
++
++ return -ENOMEM;
++}
++
++
++/* Look up a MAC in the hash table. Caller should hold table lock. */
++static inline struct fwd_struct *fwd_find_entry(const __u8 *mac,
++ struct port_fwd *fwd_set)
++{
++ cuckoo_hash_value value;
++ cuckoo_hash_mac_key key = cuckoo_mac_to_key(mac);
++
++ if (cuckoo_hash_lookup(&fwd_set->fwd_hash_table,
++ (cuckoo_hash_key *)(&key),
++ &value)) {
++ struct fwd_struct *fwd = &fwd_set->fwd_array[value];
++ DPRINTK_ON(memcmp(fwd->mac, mac, ETH_ALEN) != 0);
++ return fwd;
++ }
++
++ return NULL;
++}
++
++
++/* Initialise each nic port's fowarding table */
++void *netback_accel_init_fwd_port(void)
++{
++ struct port_fwd *fwd_set;
++
++ fwd_set = kzalloc(sizeof(struct port_fwd), GFP_KERNEL);
++ if (fwd_set == NULL) {
++ return NULL;
++ }
++
++ spin_lock_init(&fwd_set->fwd_lock);
++
++ fwd_set->fwd_array = kzalloc(sizeof (struct fwd_struct) * NUM_FWDS,
++ GFP_KERNEL);
++ if (fwd_set->fwd_array == NULL) {
++ kfree(fwd_set);
++ return NULL;
++ }
++
++ if (cuckoo_hash_init(&fwd_set->fwd_hash_table, NUM_FWDS_BITS, 8) != 0) {
++ kfree(fwd_set->fwd_array);
++ kfree(fwd_set);
++ return NULL;
++ }
++
++ INIT_LIST_HEAD(&fwd_set->fwd_list);
++
++ list_add(&fwd_set->link, &port_fwds);
++
++ return fwd_set;
++}
++
++
++void netback_accel_shutdown_fwd_port(void *fwd_priv)
++{
++ struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
++
++ BUG_ON(fwd_priv == NULL);
++
++ BUG_ON(list_empty(&port_fwds));
++ list_del(&fwd_set->link);
++
++ BUG_ON(!list_empty(&fwd_set->fwd_list));
++
++ cuckoo_hash_destroy(&fwd_set->fwd_hash_table);
++ kfree(fwd_set->fwd_array);
++ kfree(fwd_set);
++}
++
++
++int netback_accel_init_fwd()
++{
++ INIT_LIST_HEAD(&port_fwds);
++ return 0;
++}
++
++
++void netback_accel_shutdown_fwd()
++{
++ BUG_ON(!list_empty(&port_fwds));
++}
++
++
++/*
++ * Add an entry to the forwarding table. Returns -ENOMEM if no
++ * space.
++ */
++int netback_accel_fwd_add(const __u8 *mac, void *context, void *fwd_priv)
++{
++ struct fwd_struct *fwd;
++ int rc = 0, index;
++ unsigned long flags;
++ cuckoo_hash_mac_key key = cuckoo_mac_to_key(mac);
++ struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
++
++ BUG_ON(fwd_priv == NULL);
++
++ DPRINTK("Adding mac " MAC_FMT "\n", MAC_ARG(mac));
++
++ spin_lock_irqsave(&fwd_set->fwd_lock, flags);
++
++ if ((rc = fwd_find_free_entry(fwd_set)) < 0 ) {
++ spin_unlock_irqrestore(&fwd_set->fwd_lock, flags);
++ return rc;
++ }
++
++ index = rc;
++
++ /* Shouldn't already be in the table */
++ if (cuckoo_hash_lookup(&fwd_set->fwd_hash_table,
++ (cuckoo_hash_key *)(&key), &rc) != 0) {
++ spin_unlock_irqrestore(&fwd_set->fwd_lock, flags);
++ EPRINTK("MAC address " MAC_FMT " already accelerated.\n",
++ MAC_ARG(mac));
++ return -EEXIST;
++ }
++
++ if ((rc = cuckoo_hash_add(&fwd_set->fwd_hash_table,
++ (cuckoo_hash_key *)(&key), index, 1)) == 0) {
++ fwd = &fwd_set->fwd_array[index];
++ fwd->valid = 1;
++ fwd->context = context;
++ memcpy(fwd->mac, mac, ETH_ALEN);
++ list_add(&fwd->link, &fwd_set->fwd_list);
++ NETBACK_ACCEL_STATS_OP(global_stats.num_fwds++);
++ }
++
++ spin_unlock_irqrestore(&fwd_set->fwd_lock, flags);
++
++ /*
++ * No need to tell frontend that this mac address is local -
++ * it should auto-discover through packets on fastpath what is
++ * local and what is not, and just being on same server
++ * doesn't make it local (it could be on a different
++ * bridge)
++ */
++
++ return rc;
++}
++
++
++/* remove an entry from the forwarding tables. */
++void netback_accel_fwd_remove(const __u8 *mac, void *fwd_priv)
++{
++ struct fwd_struct *fwd;
++ unsigned long flags;
++ cuckoo_hash_mac_key key = cuckoo_mac_to_key(mac);
++ struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
++
++ DPRINTK("Removing mac " MAC_FMT "\n", MAC_ARG(mac));
++
++ BUG_ON(fwd_priv == NULL);
++
++ spin_lock_irqsave(&fwd_set->fwd_lock, flags);
++
++ fwd = fwd_find_entry(mac, fwd_set);
++ if (fwd != NULL) {
++ BUG_ON(list_empty(&fwd_set->fwd_list));
++ list_del(&fwd->link);
++
++ fwd->valid = 0;
++ cuckoo_hash_remove(&fwd_set->fwd_hash_table,
++ (cuckoo_hash_key *)(&key));
++ NETBACK_ACCEL_STATS_OP(global_stats.num_fwds--);
++ }
++ spin_unlock_irqrestore(&fwd_set->fwd_lock, flags);
++
++ /*
++ * No need to tell frontend that this is no longer present -
++ * the frontend is currently only interested in remote
++ * addresses and it works these out (mostly) by itself
++ */
++}
++
++
++/* Set the context pointer for a hash table entry. */
++int netback_accel_fwd_set_context(const __u8 *mac, void *context,
++ void *fwd_priv)
++{
++ struct fwd_struct *fwd;
++ unsigned long flags;
++ int rc = -ENOENT;
++ struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
++
++ BUG_ON(fwd_priv == NULL);
++
++ spin_lock_irqsave(&fwd_set->fwd_lock, flags);
++ fwd = fwd_find_entry(mac, fwd_set);
++ if (fwd != NULL) {
++ fwd->context = context;
++ rc = 0;
++ }
++ spin_unlock_irqrestore(&fwd_set->fwd_lock, flags);
++ return rc;
++}
++
++
++/**************************************************************************
++ * Process a received packet
++ **************************************************************************/
++
++/*
++ * Returns whether or not we have a match in our forward table for the
++ * this skb. Must be called with appropriate fwd_lock already held
++ */
++static struct netback_accel *for_a_vnic(struct netback_pkt_buf *skb,
++ struct port_fwd *fwd_set)
++{
++ struct fwd_struct *fwd;
++ struct netback_accel *retval = NULL;
++
++ fwd = fwd_find_entry(skb->mac.raw, fwd_set);
++ if (fwd != NULL)
++ retval = fwd->context;
++ return retval;
++}
++
++
++static inline int packet_is_arp_reply(struct sk_buff *skb)
++{
++ return skb->protocol == ntohs(ETH_P_ARP)
++ && skb->nh.arph->ar_op == ntohs(ARPOP_REPLY);
++}
++
++
++static inline void hdr_to_filt(struct ethhdr *ethhdr, struct iphdr *ip,
++ struct netback_accel_filter_spec *spec)
++{
++ spec->proto = ip->protocol;
++ spec->destip_be = ip->daddr;
++ memcpy(spec->mac, ethhdr->h_source, ETH_ALEN);
++
++ if (ip->protocol == IPPROTO_TCP) {
++ struct tcphdr *tcp = (struct tcphdr *)((char *)ip + 4 * ip->ihl);
++ spec->destport_be = tcp->dest;
++ } else {
++ struct udphdr *udp = (struct udphdr *)((char *)ip + 4 * ip->ihl);
++ EPRINTK_ON(ip->protocol != IPPROTO_UDP);
++ spec->destport_be = udp->dest;
++ }
++}
++
++
++static inline int netback_accel_can_filter(struct netback_pkt_buf *skb)
++{
++ return (skb->protocol == htons(ETH_P_IP) &&
++ ((skb->nh.iph->protocol == IPPROTO_TCP) ||
++ (skb->nh.iph->protocol == IPPROTO_UDP)));
++}
++
++
++static inline void netback_accel_filter_packet(struct netback_accel *bend,
++ struct netback_pkt_buf *skb)
++{
++ struct netback_accel_filter_spec fs;
++ struct ethhdr *eh = (struct ethhdr *)(skb->mac.raw);
++
++ hdr_to_filt(eh, skb->nh.iph, &fs);
++
++ netback_accel_filter_check_add(bend, &fs);
++}
++
++
++/*
++ * Receive a packet and do something appropriate with it. Return true
++ * to take exclusive ownership of the packet. This is verging on
++ * solarflare specific
++ */
++void netback_accel_rx_packet(struct netback_pkt_buf *skb, void *fwd_priv)
++{
++ struct netback_accel *bend;
++ struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
++ unsigned long flags;
++
++ BUG_ON(fwd_priv == NULL);
++
++ /* Checking for bcast is cheaper so do that first */
++ if (is_broadcast_ether_addr(skb->mac.raw)) {
++ /* pass through the slow path by not claiming ownership */
++ return;
++ } else if (is_multicast_ether_addr(skb->mac.raw)) {
++ /* pass through the slow path by not claiming ownership */
++ return;
++ } else {
++ /* It is unicast */
++ spin_lock_irqsave(&fwd_set->fwd_lock, flags);
++ /* We insert filter to pass it off to a VNIC */
++ if ((bend = for_a_vnic(skb, fwd_set)) != NULL)
++ if (netback_accel_can_filter(skb))
++ netback_accel_filter_packet(bend, skb);
++ spin_unlock_irqrestore(&fwd_set->fwd_lock, flags);
++ }
++ return;
++}
++
++
++void netback_accel_tx_packet(struct sk_buff *skb, void *fwd_priv)
++{
++ __u8 *mac;
++ unsigned long flags;
++ struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
++ struct fwd_struct *fwd;
++
++ BUG_ON(fwd_priv == NULL);
++
++ if (is_broadcast_ether_addr(skb->mac.raw) && packet_is_arp_reply(skb)) {
++ /*
++ * update our fast path forwarding to reflect this
++ * gratuitous ARP
++ */
++ mac = skb->mac.raw+ETH_ALEN;
++
++ DPRINTK("%s: found gratuitous ARP for " MAC_FMT "\n",
++ __FUNCTION__, MAC_ARG(mac));
++
++ spin_lock_irqsave(&fwd_set->fwd_lock, flags);
++ /*
++ * Might not be local, but let's tell them all it is,
++ * and they can restore the fastpath if they continue
++ * to get packets that way
++ */
++ list_for_each_entry(fwd, &fwd_set->fwd_list, link) {
++ struct netback_accel *bend = fwd->context;
++ if (bend != NULL)
++ netback_accel_msg_tx_new_localmac(bend, mac);
++ }
++
++ spin_unlock_irqrestore(&fwd_set->fwd_lock, flags);
++ }
++ return;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/accel.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/accel.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,393 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NETBACK_ACCEL_H
++#define NETBACK_ACCEL_H
++
++#include <linux/slab.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <linux/in.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/mutex.h>
++#include <linux/wait.h>
++
++#include <xen/xenbus.h>
++
++#include "accel_shared_fifo.h"
++#include "accel_msg_iface.h"
++#include "accel_util.h"
++
++/**************************************************************************
++ * Datatypes
++ **************************************************************************/
++
++#define NETBACK_ACCEL_DEFAULT_MAX_FILTERS (8)
++#define NETBACK_ACCEL_DEFAULT_MAX_MCASTS (8)
++#define NETBACK_ACCEL_DEFAULT_MAX_BUF_PAGES (384)
++/* Variable to store module parameter for max_buf_pages */
++extern unsigned sfc_netback_max_pages;
++
++#define NETBACK_ACCEL_STATS 1
++
++#if NETBACK_ACCEL_STATS
++#define NETBACK_ACCEL_STATS_OP(x) x
++#else
++#define NETBACK_ACCEL_STATS_OP(x)
++#endif
++
++/*! Statistics for a given backend */
++struct netback_accel_stats {
++ /*! Number of eventq wakeup events */
++ u64 evq_wakeups;
++ /*! Number of eventq timeout events */
++ u64 evq_timeouts;
++ /*! Number of filters used */
++ u32 num_filters;
++ /*! Number of buffer pages registered */
++ u32 num_buffer_pages;
++};
++
++
++/* Debug fs nodes for each of the above stats */
++struct netback_accel_dbfs {
++ struct dentry *evq_wakeups;
++ struct dentry *evq_timeouts;
++ struct dentry *num_filters;
++ struct dentry *num_buffer_pages;
++};
++
++
++/*! Resource limits for a given NIC */
++struct netback_accel_limits {
++ int max_filters; /*!< Max. number of filters to use. */
++ int max_mcasts; /*!< Max. number of mcast subscriptions */
++ int max_buf_pages; /*!< Max. number of pages of NIC buffers */
++};
++
++
++/*! The state for an instance of the back end driver. */
++struct netback_accel {
++ /*! mutex to protect this state */
++ struct mutex bend_mutex;
++
++ /*! Watches on xenstore */
++ struct xenbus_watch domu_accel_watch;
++ struct xenbus_watch config_accel_watch;
++
++ /*! Pointer to whatever device cookie ties us in to the hypervisor */
++ void *hdev_data;
++
++ /*! FIFO indices. Next page is msg FIFOs */
++ struct net_accel_shared_page *shared_page;
++
++ /*! Defer control message processing */
++ struct work_struct handle_msg;
++
++ /*! Identifies other end VM and interface.*/
++ int far_end;
++ int vif_num;
++
++ /*!< To unmap the shared pages */
++ void *sh_pages_unmap;
++
++ /* Resource tracking */
++ /*! Limits on H/W & Dom0 resources */
++ struct netback_accel_limits quotas;
++
++ /* Hardware resources */
++ /*! The H/W type of associated NIC */
++ enum net_accel_hw_type hw_type;
++ /*! State of allocation */
++ int hw_state;
++ /*! Index into ci_driver.nics[] for this interface */
++ int nic_index;
++ /*! How to set up the acceleration for this hardware */
++ int (*accel_setup)(struct netback_accel *);
++ /*! And how to stop it. */
++ void (*accel_shutdown)(struct netback_accel *);
++
++ /*! The physical/real net_dev for this interface */
++ struct net_device *net_dev;
++
++ /*! Magic pointer to locate state in fowarding table */
++ void *fwd_priv;
++
++ /*! Message FIFO */
++ sh_msg_fifo2 to_domU;
++ /*! Message FIFO */
++ sh_msg_fifo2 from_domU;
++
++ /*! General notification channel id */
++ int msg_channel;
++ /*! General notification channel irq */
++ int msg_channel_irq;
++
++ /*! Event channel id dedicated to network packet interrupts. */
++ int net_channel;
++ /*! Event channel irq dedicated to network packets interrupts */
++ int net_channel_irq;
++
++ /*! The MAC address the frontend goes by. */
++ u8 mac[ETH_ALEN];
++ /*! Driver name of associated NIC */
++ char *nicname;
++
++ /*! Array of pointers to buffer pages mapped */
++ grant_handle_t *buffer_maps;
++ u64 *buffer_addrs;
++ /*! Index into buffer_maps */
++ int buffer_maps_index;
++ /*! Max number of pages that domU is allowed/will request to map */
++ int max_pages;
++
++ /*! Pointer to hardware specific private area */
++ void *accel_hw_priv;
++
++ /*! Wait queue for changes in accelstate. */
++ wait_queue_head_t state_wait_queue;
++
++ /*! Current state of the frontend according to the xenbus
++ * watch. */
++ XenbusState frontend_state;
++
++ /*! Current state of this backend. */
++ XenbusState backend_state;
++
++ /*! Non-zero if the backend is being removed. */
++ int removing;
++
++ /*! Non-zero if the setup_vnic has been called. */
++ int vnic_is_setup;
++
++#if NETBACK_ACCEL_STATS
++ struct netback_accel_stats stats;
++#endif
++#if defined(CONFIG_DEBUG_FS)
++ char *dbfs_dir_name;
++ struct dentry *dbfs_dir;
++ struct netback_accel_dbfs dbfs;
++#endif
++
++ /*! List */
++ struct netback_accel *next_bend;
++};
++
++
++/*
++ * Values for netback_accel.hw_state. States of resource allocation
++ * we can go through
++ */
++/*! No hardware has yet been allocated. */
++#define NETBACK_ACCEL_RES_NONE (0)
++/*! Hardware has been allocated. */
++#define NETBACK_ACCEL_RES_ALLOC (1)
++#define NETBACK_ACCEL_RES_FILTER (2)
++#define NETBACK_ACCEL_RES_HWINFO (3)
++
++/*! Filtering specification. This assumes that for VNIC support we
++ * will always want wildcard entries, so only specifies the
++ * destination IP/port
++ */
++struct netback_accel_filter_spec {
++ /*! Internal, used to access efx_vi API */
++ void *filter_handle;
++
++ /*! Destination IP in network order */
++ u32 destip_be;
++ /*! Destination port in network order */
++ u16 destport_be;
++ /*! Mac address */
++ u8 mac[ETH_ALEN];
++ /*! TCP or UDP */
++ u8 proto;
++};
++
++
++/**************************************************************************
++ * From accel.c
++ **************************************************************************/
++
++/*! \brief Start up all the acceleration plugins
++ *
++ * \return 0 on success, an errno on failure
++ */
++extern int netback_accel_init_accel(void);
++
++/*! \brief Shut down all the acceleration plugins
++ */
++extern void netback_accel_shutdown_accel(void);
++
++
++/**************************************************************************
++ * From accel_fwd.c
++ **************************************************************************/
++
++/*! \brief Init the forwarding infrastructure
++ * \return 0 on success, or -ENOMEM if it couldn't get memory for the
++ * forward table
++ */
++extern int netback_accel_init_fwd(void);
++
++/*! \brief Shut down the forwarding and free memory. */
++extern void netback_accel_shutdown_fwd(void);
++
++/*! Initialise each nic port's fowarding table */
++extern void *netback_accel_init_fwd_port(void);
++extern void netback_accel_shutdown_fwd_port(void *fwd_priv);
++
++/*! \brief Add an entry to the forwarding table.
++ * \param mac : MAC address, used as hash key
++ * \param ctxt : value to associate with key (can be NULL, see
++ * netback_accel_fwd_set_context)
++ * \return 0 on success, -ENOMEM if table was full and could no grow it
++ */
++extern int netback_accel_fwd_add(const __u8 *mac, void *context,
++ void *fwd_priv);
++
++/*! \brief Remove an entry from the forwarding table.
++ * \param mac : the MAC address to remove
++ * \return nothing: it is not an error if the mac was not in the table
++ */
++extern void netback_accel_fwd_remove(const __u8 *mac, void *fwd_priv);
++
++/*! \brief Set the context pointer for an existing fwd table entry.
++ * \param mac : key that is already present in the table
++ * \param context : new value to associate with key
++ * \return 0 on success, -ENOENT if mac not present in table.
++ */
++extern int netback_accel_fwd_set_context(const __u8 *mac, void *context,
++ void *fwd_priv);
++
++/**************************************************************************
++ * From accel_msg.c
++ **************************************************************************/
++
++
++/*! \brief Send the start-of-day message that handshakes with the VNIC
++ * and tells it its MAC address.
++ *
++ * \param bend The back end driver data structure
++ * \param version The version of communication to use, e.g. NET_ACCEL_MSG_VERSION
++ */
++extern void netback_accel_msg_tx_hello(struct netback_accel *bend,
++ unsigned version);
++
++/*! \brief Send a "there's a new local mac address" message
++ *
++ * \param bend The back end driver data structure for the vnic to send
++ * the message to
++ * \param mac Pointer to the new mac address
++ */
++extern void netback_accel_msg_tx_new_localmac(struct netback_accel *bend,
++ const void *mac);
++
++/*! \brief Send a "a mac address that was local has gone away" message
++ *
++ * \param bend The back end driver data structure for the vnic to send
++ * the message to
++ * \param mac Pointer to the old mac address
++ */
++extern void netback_accel_msg_tx_old_localmac(struct netback_accel *bend,
++ const void *mac);
++
++extern void netback_accel_set_interface_state(struct netback_accel *bend,
++ int up);
++
++/*! \brief Process the message queue for a bend that has just
++ * interrupted.
++ *
++ * Demultiplexs an interrupt from the front end driver, taking
++ * messages from the fifo and taking appropriate action.
++ *
++ * \param bend The back end driver data structure
++ */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++extern void netback_accel_msg_rx_handler(struct work_struct *arg);
++#else
++extern void netback_accel_msg_rx_handler(void *bend_void);
++#endif
++
++/**************************************************************************
++ * From accel_xenbus.c
++ **************************************************************************/
++/*! List of all the bends currently in existence. */
++extern struct netback_accel *bend_list;
++extern struct mutex bend_list_mutex;
++
++/*! \brief Probe a new network interface. */
++extern int netback_accel_probe(struct xenbus_device *dev);
++
++/*! \brief Remove a network interface. */
++extern int netback_accel_remove(struct xenbus_device *dev);
++
++/*! \brief Shutdown all accelerator backends */
++extern void netback_accel_shutdown_bends(void);
++
++/*! \brief Initiate the xenbus state teardown handshake */
++extern void netback_accel_set_closing(struct netback_accel *bend);
++
++/**************************************************************************
++ * From accel_debugfs.c
++ **************************************************************************/
++/*! Global statistics */
++struct netback_accel_global_stats {
++ /*! Number of TX packets seen through driverlink */
++ u64 dl_tx_packets;
++ /*! Number of TX packets seen through driverlink we didn't like */
++ u64 dl_tx_bad_packets;
++ /*! Number of RX packets seen through driverlink */
++ u64 dl_rx_packets;
++ /*! Number of mac addresses we are forwarding to */
++ u32 num_fwds;
++};
++
++/*! Debug fs entries for each of the above stats */
++struct netback_accel_global_dbfs {
++ struct dentry *dl_tx_packets;
++ struct dentry *dl_tx_bad_packets;
++ struct dentry *dl_rx_packets;
++ struct dentry *num_fwds;
++};
++
++#if NETBACK_ACCEL_STATS
++extern struct netback_accel_global_stats global_stats;
++#endif
++
++/*! \brief Initialise the debugfs root and populate with global stats */
++extern void netback_accel_debugfs_init(void);
++
++/*! \brief Remove our debugfs root directory */
++extern void netback_accel_debugfs_fini(void);
++
++/*! \brief Add per-bend statistics to debug fs */
++extern int netback_accel_debugfs_create(struct netback_accel *bend);
++/*! \brief Remove per-bend statistics from debug fs */
++extern int netback_accel_debugfs_remove(struct netback_accel *bend);
++
++#endif /* NETBACK_ACCEL_H */
++
++
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/accel_msg.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_msg.c
+--- linux-2.6.18.8/drivers/xen/sfc_netback/accel_msg.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_msg.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,392 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <xen/evtchn.h>
++
++#include "accel.h"
++#include "accel_msg_iface.h"
++#include "accel_util.h"
++#include "accel_solarflare.h"
++
++/* Send a HELLO to front end to start things off */
++void netback_accel_msg_tx_hello(struct netback_accel *bend, unsigned version)
++{
++ unsigned long lock_state;
++ struct net_accel_msg *msg =
++ net_accel_msg_start_send(bend->shared_page,
++ &bend->to_domU, &lock_state);
++ /* The queue _cannot_ be full, we're the first users. */
++ EPRINTK_ON(msg == NULL);
++
++ if (msg != NULL) {
++ net_accel_msg_init(msg, NET_ACCEL_MSG_HELLO);
++ msg->u.hello.version = version;
++ msg->u.hello.max_pages = bend->quotas.max_buf_pages;
++ VPRINTK("Sending hello to channel %d\n", bend->msg_channel);
++ net_accel_msg_complete_send_notify(bend->shared_page,
++ &bend->to_domU,
++ &lock_state,
++ bend->msg_channel_irq);
++ }
++}
++
++/* Send a local mac message to vnic */
++static void netback_accel_msg_tx_localmac(struct netback_accel *bend,
++ int type, const void *mac)
++{
++ unsigned long lock_state;
++ struct net_accel_msg *msg;
++
++ BUG_ON(bend == NULL || mac == NULL);
++
++ VPRINTK("Sending local mac message: " MAC_FMT "\n",
++ MAC_ARG((const char *)mac));
++
++ msg = net_accel_msg_start_send(bend->shared_page, &bend->to_domU,
++ &lock_state);
++
++ if (msg != NULL) {
++ net_accel_msg_init(msg, NET_ACCEL_MSG_LOCALMAC);
++ msg->u.localmac.flags = type;
++ memcpy(msg->u.localmac.mac, mac, ETH_ALEN);
++ net_accel_msg_complete_send_notify(bend->shared_page,
++ &bend->to_domU,
++ &lock_state,
++ bend->msg_channel_irq);
++ } else {
++ /*
++ * TODO if this happens we may leave a domU
++ * fastpathing packets when they should be delivered
++ * locally. Solution is get domU to timeout entries
++ * in its fastpath lookup table when it receives no RX
++ * traffic
++ */
++ EPRINTK("%s: saw full queue, may need ARP timer to recover\n",
++ __FUNCTION__);
++ }
++}
++
++/* Send an add local mac message to vnic */
++void netback_accel_msg_tx_new_localmac(struct netback_accel *bend,
++ const void *mac)
++{
++ netback_accel_msg_tx_localmac(bend, NET_ACCEL_MSG_ADD, mac);
++}
++
++
++static int netback_accel_msg_rx_buffer_map(struct netback_accel *bend,
++ struct net_accel_msg *msg)
++{
++ int log2_pages, rc;
++
++ /* Can only allocate in power of two */
++ log2_pages = log2_ge(msg->u.mapbufs.pages, 0);
++ if (msg->u.mapbufs.pages != pow2(log2_pages)) {
++ EPRINTK("%s: Can only alloc bufs in power of 2 sizes (%d)\n",
++ __FUNCTION__, msg->u.mapbufs.pages);
++ rc = -EINVAL;
++ goto err_out;
++ }
++
++ /*
++ * Sanity. Assumes NET_ACCEL_MSG_MAX_PAGE_REQ is same for
++ * both directions/domains
++ */
++ if (msg->u.mapbufs.pages > NET_ACCEL_MSG_MAX_PAGE_REQ) {
++ EPRINTK("%s: too many pages in a single message: %d %d\n",
++ __FUNCTION__, msg->u.mapbufs.pages,
++ NET_ACCEL_MSG_MAX_PAGE_REQ);
++ rc = -EINVAL;
++ goto err_out;
++ }
++
++ if ((rc = netback_accel_add_buffers(bend, msg->u.mapbufs.pages,
++ log2_pages, msg->u.mapbufs.grants,
++ &msg->u.mapbufs.buf)) < 0) {
++ goto err_out;
++ }
++
++ msg->id |= NET_ACCEL_MSG_REPLY;
++
++ return 0;
++
++ err_out:
++ EPRINTK("%s: err_out\n", __FUNCTION__);
++ msg->id |= NET_ACCEL_MSG_ERROR | NET_ACCEL_MSG_REPLY;
++ return rc;
++}
++
++
++/* Hint from frontend that one of our filters is out of date */
++static int netback_accel_process_fastpath(struct netback_accel *bend,
++ struct net_accel_msg *msg)
++{
++ struct netback_accel_filter_spec spec;
++
++ if (msg->u.fastpath.flags & NET_ACCEL_MSG_REMOVE) {
++ /*
++ * Would be nice to BUG() this but would leave us
++ * vulnerable to naughty frontend
++ */
++ EPRINTK_ON(msg->u.fastpath.flags & NET_ACCEL_MSG_ADD);
++
++ memcpy(spec.mac, msg->u.fastpath.mac, ETH_ALEN);
++ spec.destport_be = msg->u.fastpath.port;
++ spec.destip_be = msg->u.fastpath.ip;
++ spec.proto = msg->u.fastpath.proto;
++
++ netback_accel_filter_remove_spec(bend, &spec);
++ }
++
++ return 0;
++}
++
++
++/* Flow control for message queues */
++inline void set_queue_not_full(struct netback_accel *bend)
++{
++ if (!test_and_set_bit(NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL_B,
++ (unsigned long *)&bend->shared_page->aflags))
++ notify_remote_via_irq(bend->msg_channel_irq);
++ else
++ VPRINTK("queue not full bit already set, not signalling\n");
++}
++
++
++/* Flow control for message queues */
++inline void set_queue_full(struct netback_accel *bend)
++{
++ if (!test_and_set_bit(NET_ACCEL_MSG_AFLAGS_QUEUE0FULL_B,
++ (unsigned long *)&bend->shared_page->aflags))
++ notify_remote_via_irq(bend->msg_channel_irq);
++ else
++ VPRINTK("queue full bit already set, not signalling\n");
++}
++
++
++void netback_accel_set_interface_state(struct netback_accel *bend, int up)
++{
++ bend->shared_page->net_dev_up = up;
++ if (!test_and_set_bit(NET_ACCEL_MSG_AFLAGS_NETUPDOWN_B,
++ (unsigned long *)&bend->shared_page->aflags))
++ notify_remote_via_irq(bend->msg_channel_irq);
++ else
++ VPRINTK("interface up/down bit already set, not signalling\n");
++}
++
++
++static int check_rx_hello_version(unsigned version)
++{
++ /* Should only happen if there's been a version mismatch */
++ BUG_ON(version == NET_ACCEL_MSG_VERSION);
++
++ if (version > NET_ACCEL_MSG_VERSION) {
++ /* Newer protocol, we must refuse */
++ return -EPROTO;
++ }
++
++ if (version < NET_ACCEL_MSG_VERSION) {
++ /*
++ * We are newer, so have discretion to accept if we
++ * wish. For now however, just reject
++ */
++ return -EPROTO;
++ }
++
++ return -EINVAL;
++}
++
++
++static int process_rx_msg(struct netback_accel *bend,
++ struct net_accel_msg *msg)
++{
++ int err = 0;
++
++ switch (msg->id) {
++ case NET_ACCEL_MSG_REPLY | NET_ACCEL_MSG_HELLO:
++ /* Reply to a HELLO; mark ourselves as connected */
++ DPRINTK("got Hello reply, version %.8x\n",
++ msg->u.hello.version);
++
++ /*
++ * Check that we've not successfully done this
++ * already. NB no check at the moment that this reply
++ * comes after we've actually sent a HELLO as that's
++ * not possible with the current code structure
++ */
++ if (bend->hw_state != NETBACK_ACCEL_RES_NONE)
++ return -EPROTO;
++
++ /* Store max_pages for accel_setup */
++ if (msg->u.hello.max_pages > bend->quotas.max_buf_pages) {
++ EPRINTK("More pages than quota allows (%d > %d)\n",
++ msg->u.hello.max_pages,
++ bend->quotas.max_buf_pages);
++ /* Force it down to the quota */
++ msg->u.hello.max_pages = bend->quotas.max_buf_pages;
++ }
++ bend->max_pages = msg->u.hello.max_pages;
++
++ /* Set up the hardware visible to the other end */
++ err = bend->accel_setup(bend);
++ if (err) {
++ /* This is fatal */
++ DPRINTK("Hello gave accel_setup error %d\n", err);
++ netback_accel_set_closing(bend);
++ } else {
++ /*
++ * Now add the context so that packet
++ * forwarding will commence
++ */
++ netback_accel_fwd_set_context(bend->mac, bend,
++ bend->fwd_priv);
++ }
++ break;
++ case NET_ACCEL_MSG_REPLY | NET_ACCEL_MSG_HELLO | NET_ACCEL_MSG_ERROR:
++ EPRINTK("got Hello error, versions us:%.8x them:%.8x\n",
++ NET_ACCEL_MSG_VERSION, msg->u.hello.version);
++
++ if (bend->hw_state != NETBACK_ACCEL_RES_NONE)
++ return -EPROTO;
++
++ if (msg->u.hello.version != NET_ACCEL_MSG_VERSION) {
++ /* Error is due to version mismatch */
++ err = check_rx_hello_version(msg->u.hello.version);
++ if (err == 0) {
++ /*
++ * It's OK to be compatible, send
++ * another hello with compatible version
++ */
++ netback_accel_msg_tx_hello
++ (bend, msg->u.hello.version);
++ } else {
++ /*
++ * Tell frontend that we're not going to
++ * send another HELLO by going to Closing.
++ */
++ netback_accel_set_closing(bend);
++ }
++ }
++ break;
++ case NET_ACCEL_MSG_MAPBUF:
++ VPRINTK("Got mapped buffers request %d\n",
++ msg->u.mapbufs.reqid);
++
++ if (bend->hw_state == NETBACK_ACCEL_RES_NONE)
++ return -EPROTO;
++
++ /*
++ * Frontend wants a buffer table entry for the
++ * supplied pages
++ */
++ err = netback_accel_msg_rx_buffer_map(bend, msg);
++ if (net_accel_msg_reply_notify(bend->shared_page,
++ bend->msg_channel_irq,
++ &bend->to_domU, msg)) {
++ /*
++ * This is fatal as we can't tell the frontend
++ * about the problem through the message
++ * queue, and so would otherwise stalemate
++ */
++ netback_accel_set_closing(bend);
++ }
++ break;
++ case NET_ACCEL_MSG_FASTPATH:
++ DPRINTK("Got fastpath request\n");
++
++ if (bend->hw_state == NETBACK_ACCEL_RES_NONE)
++ return -EPROTO;
++
++ err = netback_accel_process_fastpath(bend, msg);
++ break;
++ default:
++ EPRINTK("Huh? Message code is %x\n", msg->id);
++ err = -EPROTO;
++ break;
++ }
++ return err;
++}
++
++
++/* Demultiplex an IRQ from the frontend driver. */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++void netback_accel_msg_rx_handler(struct work_struct *arg)
++#else
++void netback_accel_msg_rx_handler(void *bend_void)
++#endif
++{
++ struct net_accel_msg msg;
++ int err, queue_was_full = 0;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ struct netback_accel *bend =
++ container_of(arg, struct netback_accel, handle_msg);
++#else
++ struct netback_accel *bend = (struct netback_accel *)bend_void;
++#endif
++
++ mutex_lock(&bend->bend_mutex);
++
++ /*
++ * This happens when the shared pages have been unmapped, but
++ * the workqueue not flushed yet
++ */
++ if (bend->shared_page == NULL)
++ goto done;
++
++ if ((bend->shared_page->aflags &
++ NET_ACCEL_MSG_AFLAGS_TO_DOM0_MASK) != 0) {
++ if (bend->shared_page->aflags &
++ NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL) {
++ /* We've been told there may now be space. */
++ clear_bit(NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL_B,
++ (unsigned long *)&bend->shared_page->aflags);
++ }
++
++ if (bend->shared_page->aflags &
++ NET_ACCEL_MSG_AFLAGS_QUEUEUFULL) {
++ clear_bit(NET_ACCEL_MSG_AFLAGS_QUEUEUFULL_B,
++ (unsigned long *)&bend->shared_page->aflags);
++ queue_was_full = 1;
++ }
++ }
++
++ while ((err = net_accel_msg_recv(bend->shared_page, &bend->from_domU,
++ &msg)) == 0) {
++ err = process_rx_msg(bend, &msg);
++
++ if (err != 0) {
++ EPRINTK("%s: Error %d\n", __FUNCTION__, err);
++ goto err;
++ }
++ }
++
++ err:
++ /* There will be space now if we can make any. */
++ if (queue_was_full)
++ set_queue_not_full(bend);
++ done:
++ mutex_unlock(&bend->bend_mutex);
++
++ return;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/accel_solarflare.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_solarflare.c
+--- linux-2.6.18.8/drivers/xen/sfc_netback/accel_solarflare.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_solarflare.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1253 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include "common.h"
++
++#include "accel.h"
++#include "accel_solarflare.h"
++#include "accel_msg_iface.h"
++#include "accel_util.h"
++
++#include "accel_cuckoo_hash.h"
++
++#include "ci/driver/resource/efx_vi.h"
++
++#include "ci/efrm/nic_table.h"
++#include "ci/efhw/public.h"
++
++#include <xen/evtchn.h>
++#include <xen/driver_util.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++
++#include "driverlink_api.h"
++
++#define SF_XEN_RX_USR_BUF_SIZE 2048
++
++struct falcon_bend_accel_priv {
++ struct efx_vi_state *efx_vih;
++
++ /*! Array of pointers to dma_map state, used so VNIC can
++ * request their removal in a single message
++ */
++ struct efx_vi_dma_map_state **dma_maps;
++ /*! Index into dma_maps */
++ int dma_maps_index;
++
++ /*! Serialises access to filters */
++ spinlock_t filter_lock;
++ /*! Bitmap of which filters are free */
++ unsigned long free_filters;
++ /*! Used for index normalisation */
++ u32 filter_idx_mask;
++ struct netback_accel_filter_spec *fspecs;
++ cuckoo_hash_table filter_hash_table;
++
++ u32 txdmaq_gnt;
++ u32 rxdmaq_gnt;
++ u32 doorbell_gnt;
++ u32 evq_rptr_gnt;
++ u32 evq_mem_gnts[EF_HW_FALCON_EVQ_PAGES];
++ u32 evq_npages;
++};
++
++/* Forward declaration */
++static int netback_accel_filter_init(struct netback_accel *);
++static void netback_accel_filter_shutdown(struct netback_accel *);
++
++/**************************************************************************
++ *
++ * Driverlink stuff
++ *
++ **************************************************************************/
++
++struct driverlink_port {
++ struct list_head link;
++ enum net_accel_hw_type type;
++ struct net_device *net_dev;
++ struct efx_dl_device *efx_dl_dev;
++ int nic_index;
++ void *fwd_priv;
++};
++
++static struct list_head dl_ports;
++
++/* This mutex protects global state, such as the dl_ports list */
++DEFINE_MUTEX(accel_mutex);
++
++static int init_done = 0;
++
++/* The DL callbacks */
++
++
++#if defined(EFX_USE_FASTCALL)
++static enum efx_veto fastcall
++#else
++static enum efx_veto
++#endif
++bend_dl_tx_packet(struct efx_dl_device *efx_dl_dev,
++ struct sk_buff *skb)
++{
++ struct driverlink_port *port = efx_dl_dev->priv;
++
++ BUG_ON(port == NULL);
++
++ NETBACK_ACCEL_STATS_OP(global_stats.dl_tx_packets++);
++ if (skb->mac.raw != NULL)
++ netback_accel_tx_packet(skb, port->fwd_priv);
++ else {
++ DPRINTK("Ignoring packet with missing mac address\n");
++ NETBACK_ACCEL_STATS_OP(global_stats.dl_tx_bad_packets++);
++ }
++ return EFX_ALLOW_PACKET;
++}
++
++/* EFX_USE_FASTCALL */
++#if defined(EFX_USE_FASTCALL)
++static enum efx_veto fastcall
++#else
++static enum efx_veto
++#endif
++bend_dl_rx_packet(struct efx_dl_device *efx_dl_dev,
++ const char *pkt_buf, int pkt_len)
++{
++ struct driverlink_port *port = efx_dl_dev->priv;
++ struct netback_pkt_buf pkt;
++ struct ethhdr *eh;
++
++ BUG_ON(port == NULL);
++
++ pkt.mac.raw = (char *)pkt_buf;
++ pkt.nh.raw = (char *)pkt_buf + ETH_HLEN;
++ eh = (struct ethhdr *)pkt_buf;
++ pkt.protocol = eh->h_proto;
++
++ NETBACK_ACCEL_STATS_OP(global_stats.dl_rx_packets++);
++ netback_accel_rx_packet(&pkt, port->fwd_priv);
++ return EFX_ALLOW_PACKET;
++}
++
++
++/* Callbacks we'd like to get from the netdriver through driverlink */
++struct efx_dl_callbacks bend_dl_callbacks =
++ {
++ .tx_packet = bend_dl_tx_packet,
++ .rx_packet = bend_dl_rx_packet,
++ };
++
++
++static struct netback_accel_hooks accel_hooks = {
++ THIS_MODULE,
++ &netback_accel_probe,
++ &netback_accel_remove
++};
++
++
++/*
++ * Handy helper which given an efx_dl_device works out which
++ * efab_nic_t index into efrm_nic_table.nics[] it corresponds to
++ */
++static int efx_device_to_efab_nic_index(struct efx_dl_device *efx_dl_dev)
++{
++ int i;
++
++ for (i = 0; i < EFHW_MAX_NR_DEVS; i++) {
++ struct efhw_nic *nic = efrm_nic_table.nic[i];
++
++ /*
++ * It's possible for the nic structure to have not
++ * been initialised if the resource driver failed its
++ * driverlink probe
++ */
++ if (nic == NULL || nic->net_driver_dev == NULL)
++ continue;
++
++ /* Work out if these are talking about the same NIC */
++ if (nic->net_driver_dev->pci_dev == efx_dl_dev->pci_dev)
++ return i;
++ }
++
++ return -1;
++}
++
++
++/* Driver link probe - register our callbacks */
++static int bend_dl_probe(struct efx_dl_device *efx_dl_dev,
++ const struct net_device *net_dev,
++ const struct efx_dl_device_info *dev_info,
++ const char* silicon_rev)
++{
++ int rc;
++ enum net_accel_hw_type type;
++ struct driverlink_port *port;
++
++ DPRINTK("%s: %s\n", __FUNCTION__, silicon_rev);
++
++ if (strcmp(silicon_rev, "falcon/a1") == 0)
++ type = NET_ACCEL_MSG_HWTYPE_FALCON_A;
++ else if (strcmp(silicon_rev, "falcon/b0") == 0)
++ type = NET_ACCEL_MSG_HWTYPE_FALCON_B;
++ else {
++ EPRINTK("%s: unsupported silicon %s\n", __FUNCTION__,
++ silicon_rev);
++ rc = -EINVAL;
++ goto fail1;
++ }
++
++ port = kmalloc(sizeof(struct driverlink_port), GFP_KERNEL);
++ if (port == NULL) {
++ EPRINTK("%s: no memory for dl probe\n", __FUNCTION__);
++ rc = -ENOMEM;
++ goto fail1;
++ }
++
++ port->efx_dl_dev = efx_dl_dev;
++ efx_dl_dev->priv = port;
++
++ port->nic_index = efx_device_to_efab_nic_index(efx_dl_dev);
++ if (port->nic_index < 0) {
++ /*
++ * This can happen in theory if the resource driver
++ * failed to initialise properly
++ */
++ EPRINTK("%s: nic structure not found\n", __FUNCTION__);
++ rc = -EINVAL;
++ goto fail2;
++ }
++
++ port->fwd_priv = netback_accel_init_fwd_port();
++ if (port->fwd_priv == NULL) {
++ EPRINTK("%s: failed to set up forwarding for port\n",
++ __FUNCTION__);
++ rc = -ENOMEM;
++ goto fail2;
++ }
++
++ rc = efx_dl_register_callbacks(efx_dl_dev, &bend_dl_callbacks);
++ if (rc != 0) {
++ EPRINTK("%s: register_callbacks failed\n", __FUNCTION__);
++ goto fail3;
++ }
++
++ port->type = type;
++ port->net_dev = (struct net_device *)net_dev;
++
++ mutex_lock(&accel_mutex);
++ list_add(&port->link, &dl_ports);
++ mutex_unlock(&accel_mutex);
++
++ rc = netback_connect_accelerator(NETBACK_ACCEL_VERSION, 0,
++ port->net_dev->name, &accel_hooks);
++
++ if (rc < 0) {
++ EPRINTK("Xen netback accelerator version mismatch\n");
++ goto fail4;
++ } else if (rc > 0) {
++ /*
++ * In future may want to add backwards compatibility
++ * and accept certain subsets of previous versions
++ */
++ EPRINTK("Xen netback accelerator version mismatch\n");
++ goto fail4;
++ }
++
++ return 0;
++
++ fail4:
++ mutex_lock(&accel_mutex);
++ list_del(&port->link);
++ mutex_unlock(&accel_mutex);
++
++ efx_dl_unregister_callbacks(efx_dl_dev, &bend_dl_callbacks);
++ fail3:
++ netback_accel_shutdown_fwd_port(port->fwd_priv);
++ fail2:
++ efx_dl_dev->priv = NULL;
++ kfree(port);
++ fail1:
++ return rc;
++}
++
++
++static void bend_dl_remove(struct efx_dl_device *efx_dl_dev)
++{
++ struct driverlink_port *port;
++
++ DPRINTK("Unregistering driverlink callbacks.\n");
++
++ mutex_lock(&accel_mutex);
++
++ port = (struct driverlink_port *)efx_dl_dev->priv;
++
++ BUG_ON(list_empty(&dl_ports));
++ BUG_ON(port == NULL);
++ BUG_ON(port->efx_dl_dev != efx_dl_dev);
++
++ netback_disconnect_accelerator(0, port->net_dev->name);
++
++ list_del(&port->link);
++
++ mutex_unlock(&accel_mutex);
++
++ efx_dl_unregister_callbacks(efx_dl_dev, &bend_dl_callbacks);
++ netback_accel_shutdown_fwd_port(port->fwd_priv);
++
++ efx_dl_dev->priv = NULL;
++ kfree(port);
++
++ return;
++}
++
++
++static struct efx_dl_driver bend_dl_driver =
++ {
++ .name = "SFC Xen backend",
++ .probe = bend_dl_probe,
++ .remove = bend_dl_remove,
++ };
++
++
++int netback_accel_sf_init(void)
++{
++ int rc, nic_i;
++ struct efhw_nic *nic;
++
++ INIT_LIST_HEAD(&dl_ports);
++
++ rc = efx_dl_register_driver(&bend_dl_driver);
++ /* If we couldn't find the NET driver, give up */
++ if (rc == -ENOENT)
++ return rc;
++
++ if (rc == 0) {
++ EFRM_FOR_EACH_NIC(nic_i, nic)
++ falcon_nic_set_rx_usr_buf_size(nic,
++ SF_XEN_RX_USR_BUF_SIZE);
++ }
++
++ init_done = (rc == 0);
++ return rc;
++}
++
++
++void netback_accel_sf_shutdown(void)
++{
++ if (!init_done)
++ return;
++ DPRINTK("Unregistering driverlink driver\n");
++
++ /*
++ * This will trigger removal callbacks for all the devices, which
++ * will unregister their callbacks, disconnect from netfront, etc.
++ */
++ efx_dl_unregister_driver(&bend_dl_driver);
++}
++
++
++int netback_accel_sf_hwtype(struct netback_accel *bend)
++{
++ struct driverlink_port *port;
++
++ mutex_lock(&accel_mutex);
++
++ list_for_each_entry(port, &dl_ports, link) {
++ if (strcmp(bend->nicname, port->net_dev->name) == 0) {
++ bend->hw_type = port->type;
++ bend->accel_setup = netback_accel_setup_vnic_hw;
++ bend->accel_shutdown = netback_accel_shutdown_vnic_hw;
++ bend->fwd_priv = port->fwd_priv;
++ /* This is just needed to pass to efx_vi_alloc */
++ bend->nic_index = port->nic_index;
++ bend->net_dev = port->net_dev;
++ mutex_unlock(&accel_mutex);
++ return 0;
++ }
++ }
++
++ mutex_unlock(&accel_mutex);
++
++ EPRINTK("Failed to identify backend device '%s' with a NIC\n",
++ bend->nicname);
++
++ return -ENOENT;
++}
++
++
++/****************************************************************************
++ * Resource management code
++ ***************************************************************************/
++
++static int alloc_page_state(struct netback_accel *bend, int max_pages)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv;
++
++ if (max_pages < 0 || max_pages > bend->quotas.max_buf_pages) {
++ EPRINTK("%s: invalid max_pages: %d\n", __FUNCTION__, max_pages);
++ return -EINVAL;
++ }
++
++ accel_hw_priv = kzalloc(sizeof(struct falcon_bend_accel_priv),
++ GFP_KERNEL);
++ if (accel_hw_priv == NULL) {
++ EPRINTK("%s: no memory for accel_hw_priv\n", __FUNCTION__);
++ return -ENOMEM;
++ }
++
++ accel_hw_priv->dma_maps = kzalloc
++ (sizeof(struct efx_vi_dma_map_state **) *
++ (max_pages / NET_ACCEL_MSG_MAX_PAGE_REQ), GFP_KERNEL);
++ if (accel_hw_priv->dma_maps == NULL) {
++ EPRINTK("%s: no memory for dma_maps\n", __FUNCTION__);
++ kfree(accel_hw_priv);
++ return -ENOMEM;
++ }
++
++ bend->buffer_maps = kzalloc(sizeof(struct vm_struct *) * max_pages,
++ GFP_KERNEL);
++ if (bend->buffer_maps == NULL) {
++ EPRINTK("%s: no memory for buffer_maps\n", __FUNCTION__);
++ kfree(accel_hw_priv->dma_maps);
++ kfree(accel_hw_priv);
++ return -ENOMEM;
++ }
++
++ bend->buffer_addrs = kzalloc(sizeof(u64) * max_pages, GFP_KERNEL);
++ if (bend->buffer_addrs == NULL) {
++ kfree(bend->buffer_maps);
++ kfree(accel_hw_priv->dma_maps);
++ kfree(accel_hw_priv);
++ return -ENOMEM;
++ }
++
++ bend->accel_hw_priv = accel_hw_priv;
++
++ return 0;
++}
++
++
++static int free_page_state(struct netback_accel *bend)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv;
++
++ DPRINTK("%s: %p\n", __FUNCTION__, bend);
++
++ accel_hw_priv = bend->accel_hw_priv;
++
++ if (accel_hw_priv) {
++ kfree(accel_hw_priv->dma_maps);
++ kfree(bend->buffer_maps);
++ kfree(bend->buffer_addrs);
++ kfree(accel_hw_priv);
++ bend->accel_hw_priv = NULL;
++ bend->max_pages = 0;
++ }
++
++ return 0;
++}
++
++
++/* The timeout event callback for the event q */
++static void bend_evq_timeout(void *context, int is_timeout)
++{
++ struct netback_accel *bend = (struct netback_accel *)context;
++ if (is_timeout) {
++ /* Pass event to vnic front end driver */
++ VPRINTK("timeout event to %d\n", bend->net_channel);
++ NETBACK_ACCEL_STATS_OP(bend->stats.evq_timeouts++);
++ notify_remote_via_irq(bend->net_channel_irq);
++ } else {
++ /* It's a wakeup event, used by Falcon */
++ VPRINTK("wakeup to %d\n", bend->net_channel);
++ NETBACK_ACCEL_STATS_OP(bend->stats.evq_wakeups++);
++ notify_remote_via_irq(bend->net_channel_irq);
++ }
++}
++
++
++/*
++ * Create the eventq and associated gubbins for communication with the
++ * front end vnic driver
++ */
++static int ef_get_vnic(struct netback_accel *bend)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv;
++ int rc = 0;
++
++ BUG_ON(bend->hw_state != NETBACK_ACCEL_RES_NONE);
++
++ /* Allocate page related state and accel_hw_priv */
++ rc = alloc_page_state(bend, bend->max_pages);
++ if (rc != 0) {
++ EPRINTK("Failed to allocate page state: %d\n", rc);
++ return rc;
++ }
++
++ accel_hw_priv = bend->accel_hw_priv;
++
++ rc = efx_vi_alloc(&accel_hw_priv->efx_vih, bend->nic_index);
++ if (rc != 0) {
++ EPRINTK("%s: efx_vi_alloc failed %d\n", __FUNCTION__, rc);
++ free_page_state(bend);
++ return rc;
++ }
++
++ rc = efx_vi_eventq_register_callback(accel_hw_priv->efx_vih,
++ bend_evq_timeout,
++ bend);
++ if (rc != 0) {
++ EPRINTK("%s: register_callback failed %d\n", __FUNCTION__, rc);
++ efx_vi_free(accel_hw_priv->efx_vih);
++ free_page_state(bend);
++ return rc;
++ }
++
++ bend->hw_state = NETBACK_ACCEL_RES_ALLOC;
++
++ return 0;
++}
++
++
++static void ef_free_vnic(struct netback_accel *bend)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++
++ BUG_ON(bend->hw_state != NETBACK_ACCEL_RES_ALLOC);
++
++ efx_vi_eventq_kill_callback(accel_hw_priv->efx_vih);
++
++ DPRINTK("Hardware is freeable. Will proceed.\n");
++
++ efx_vi_free(accel_hw_priv->efx_vih);
++ accel_hw_priv->efx_vih = NULL;
++
++ VPRINTK("Free page state...\n");
++ free_page_state(bend);
++
++ bend->hw_state = NETBACK_ACCEL_RES_NONE;
++}
++
++
++static inline void ungrant_or_crash(grant_ref_t gntref, int domain) {
++ if (net_accel_ungrant_page(gntref) == -EBUSY)
++ net_accel_shutdown_remote(domain);
++}
++
++
++static void netback_accel_release_hwinfo(struct netback_accel *bend)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++ int i;
++
++ DPRINTK("Remove dma q grants %d %d\n", accel_hw_priv->txdmaq_gnt,
++ accel_hw_priv->rxdmaq_gnt);
++ ungrant_or_crash(accel_hw_priv->txdmaq_gnt, bend->far_end);
++ ungrant_or_crash(accel_hw_priv->rxdmaq_gnt, bend->far_end);
++
++ DPRINTK("Remove doorbell grant %d\n", accel_hw_priv->doorbell_gnt);
++ ungrant_or_crash(accel_hw_priv->doorbell_gnt, bend->far_end);
++
++ if (bend->hw_type == NET_ACCEL_MSG_HWTYPE_FALCON_A) {
++ DPRINTK("Remove rptr grant %d\n", accel_hw_priv->evq_rptr_gnt);
++ ungrant_or_crash(accel_hw_priv->evq_rptr_gnt, bend->far_end);
++ }
++
++ for (i = 0; i < accel_hw_priv->evq_npages; i++) {
++ DPRINTK("Remove evq grant %d\n", accel_hw_priv->evq_mem_gnts[i]);
++ ungrant_or_crash(accel_hw_priv->evq_mem_gnts[i], bend->far_end);
++ }
++
++ bend->hw_state = NETBACK_ACCEL_RES_FILTER;
++
++ return;
++}
++
++
++static int ef_bend_hwinfo_falcon_common(struct netback_accel *bend,
++ struct net_accel_hw_falcon_b *hwinfo)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++ struct efx_vi_hw_resource_metadata res_mdata;
++ struct efx_vi_hw_resource res_array[EFX_VI_HW_RESOURCE_MAXSIZE];
++ int rc, len = EFX_VI_HW_RESOURCE_MAXSIZE, i, pfn = 0;
++ unsigned long txdmaq_pfn = 0, rxdmaq_pfn = 0;
++
++ rc = efx_vi_hw_resource_get_phys(accel_hw_priv->efx_vih, &res_mdata,
++ res_array, &len);
++ if (rc != 0) {
++ DPRINTK("%s: resource_get_phys returned %d\n",
++ __FUNCTION__, rc);
++ return rc;
++ }
++
++ if (res_mdata.version != 0)
++ return -EPROTO;
++
++ hwinfo->nic_arch = res_mdata.nic_arch;
++ hwinfo->nic_variant = res_mdata.nic_variant;
++ hwinfo->nic_revision = res_mdata.nic_revision;
++
++ hwinfo->evq_order = res_mdata.evq_order;
++ hwinfo->evq_offs = res_mdata.evq_offs;
++ hwinfo->evq_capacity = res_mdata.evq_capacity;
++ hwinfo->instance = res_mdata.instance;
++ hwinfo->rx_capacity = res_mdata.rx_capacity;
++ hwinfo->tx_capacity = res_mdata.tx_capacity;
++
++ VPRINTK("evq_order %d evq_offs %d evq_cap %d inst %d rx_cap %d tx_cap %d\n",
++ hwinfo->evq_order, hwinfo->evq_offs, hwinfo->evq_capacity,
++ hwinfo->instance, hwinfo->rx_capacity, hwinfo->tx_capacity);
++
++ for (i = 0; i < len; i++) {
++ struct efx_vi_hw_resource *res = &(res_array[i]);
++ switch (res->type) {
++ case EFX_VI_HW_RESOURCE_TXDMAQ:
++ txdmaq_pfn = page_to_pfn(virt_to_page(res->address));
++ break;
++ case EFX_VI_HW_RESOURCE_RXDMAQ:
++ rxdmaq_pfn = page_to_pfn(virt_to_page(res->address));
++ break;
++ case EFX_VI_HW_RESOURCE_EVQTIMER:
++ break;
++ case EFX_VI_HW_RESOURCE_EVQRPTR:
++ case EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET:
++ hwinfo->evq_rptr = res->address;
++ break;
++ case EFX_VI_HW_RESOURCE_EVQMEMKVA:
++ accel_hw_priv->evq_npages = 1 << res_mdata.evq_order;
++ pfn = page_to_pfn(virt_to_page(res->address));
++ break;
++ case EFX_VI_HW_RESOURCE_BELLPAGE:
++ hwinfo->doorbell_mfn = res->address;
++ break;
++ default:
++ EPRINTK("%s: Unknown hardware resource type %d\n",
++ __FUNCTION__, res->type);
++ break;
++ }
++ }
++
++ VPRINTK("Passing txdmaq page pfn %lx\n", txdmaq_pfn);
++ accel_hw_priv->txdmaq_gnt = hwinfo->txdmaq_gnt =
++ net_accel_grant_page(bend->hdev_data, pfn_to_mfn(txdmaq_pfn),
++ 0);
++
++ VPRINTK("Passing rxdmaq page pfn %lx\n", rxdmaq_pfn);
++ accel_hw_priv->rxdmaq_gnt = hwinfo->rxdmaq_gnt =
++ net_accel_grant_page(bend->hdev_data, pfn_to_mfn(rxdmaq_pfn),
++ 0);
++
++ VPRINTK("Passing doorbell page mfn %x\n", hwinfo->doorbell_mfn);
++ /* Make the relevant H/W pages mappable by the far end */
++ accel_hw_priv->doorbell_gnt = hwinfo->doorbell_gnt =
++ net_accel_grant_page(bend->hdev_data, hwinfo->doorbell_mfn, 1);
++
++ /* Now do the same for the memory pages */
++ /* Convert the page + length we got back for the evq to grants. */
++ for (i = 0; i < accel_hw_priv->evq_npages; i++) {
++ accel_hw_priv->evq_mem_gnts[i] = hwinfo->evq_mem_gnts[i] =
++ net_accel_grant_page(bend->hdev_data, pfn_to_mfn(pfn), 0);
++ VPRINTK("Got grant %u for evq pfn %x\n", hwinfo->evq_mem_gnts[i],
++ pfn);
++ pfn++;
++ }
++
++ return 0;
++}
++
++
++static int ef_bend_hwinfo_falcon_a(struct netback_accel *bend,
++ struct net_accel_hw_falcon_a *hwinfo)
++{
++ int rc;
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++
++ if ((rc = ef_bend_hwinfo_falcon_common(bend, &hwinfo->common)) != 0)
++ return rc;
++
++ /*
++ * Note that unlike the above, where the message field is the
++ * page number, here evq_rptr is the entire address because
++ * it is currently a pointer into the densely mapped timer page.
++ */
++ VPRINTK("Passing evq_rptr pfn %x for rptr %x\n",
++ hwinfo->common.evq_rptr >> PAGE_SHIFT,
++ hwinfo->common.evq_rptr);
++ rc = net_accel_grant_page(bend->hdev_data,
++ hwinfo->common.evq_rptr >> PAGE_SHIFT, 0);
++ if (rc < 0)
++ return rc;
++
++ accel_hw_priv->evq_rptr_gnt = hwinfo->evq_rptr_gnt = rc;
++ VPRINTK("evq_rptr_gnt got %d\n", hwinfo->evq_rptr_gnt);
++
++ return 0;
++}
++
++
++static int ef_bend_hwinfo_falcon_b(struct netback_accel *bend,
++ struct net_accel_hw_falcon_b *hwinfo)
++{
++ return ef_bend_hwinfo_falcon_common(bend, hwinfo);
++}
++
++
++/*
++ * Fill in the message with a description of the hardware resources, based on
++ * the H/W type
++ */
++static int netback_accel_hwinfo(struct netback_accel *bend,
++ struct net_accel_msg_hw *msgvi)
++{
++ int rc = 0;
++
++ BUG_ON(bend->hw_state != NETBACK_ACCEL_RES_FILTER);
++
++ msgvi->type = bend->hw_type;
++ switch (bend->hw_type) {
++ case NET_ACCEL_MSG_HWTYPE_FALCON_A:
++ rc = ef_bend_hwinfo_falcon_a(bend, &msgvi->resources.falcon_a);
++ break;
++ case NET_ACCEL_MSG_HWTYPE_FALCON_B:
++ rc = ef_bend_hwinfo_falcon_b(bend, &msgvi->resources.falcon_b);
++ break;
++ case NET_ACCEL_MSG_HWTYPE_NONE:
++ /* Nothing to do. The slow path should just work. */
++ break;
++ }
++
++ if (rc == 0)
++ bend->hw_state = NETBACK_ACCEL_RES_HWINFO;
++
++ return rc;
++}
++
++
++/* Allocate hardware resources and make them available to the client domain */
++int netback_accel_setup_vnic_hw(struct netback_accel *bend)
++{
++ struct net_accel_msg msg;
++ int err;
++
++ /* Allocate the event queue, VI and so on. */
++ err = ef_get_vnic(bend);
++ if (err) {
++ EPRINTK("Failed to allocate hardware resource for bend:"
++ "error %d\n", err);
++ return err;
++ }
++
++ /* Set up the filter management */
++ err = netback_accel_filter_init(bend);
++ if (err) {
++ EPRINTK("Filter setup failed, error %d", err);
++ ef_free_vnic(bend);
++ return err;
++ }
++
++ net_accel_msg_init(&msg, NET_ACCEL_MSG_SETHW);
++
++ /*
++ * Extract the low-level hardware info we will actually pass to the
++ * other end, and set up the grants/ioremap permissions needed
++ */
++ err = netback_accel_hwinfo(bend, &msg.u.hw);
++
++ if (err != 0) {
++ netback_accel_filter_shutdown(bend);
++ ef_free_vnic(bend);
++ return err;
++ }
++
++ /* Send the message, this is a reply to a hello-reply */
++ err = net_accel_msg_reply_notify(bend->shared_page,
++ bend->msg_channel_irq,
++ &bend->to_domU, &msg);
++
++ /*
++ * The message should succeed as it's logically a reply and we
++ * guarantee space for replies, but a misbehaving frontend
++ * could result in that behaviour, so be tolerant
++ */
++ if (err != 0) {
++ netback_accel_release_hwinfo(bend);
++ netback_accel_filter_shutdown(bend);
++ ef_free_vnic(bend);
++ }
++
++ return err;
++}
++
++
++/* Free hardware resources */
++void netback_accel_shutdown_vnic_hw(struct netback_accel *bend)
++{
++ /*
++ * Only try and release resources if accel_hw_priv was setup,
++ * otherwise there is nothing to do as we're on "null-op"
++ * acceleration
++ */
++ switch (bend->hw_state) {
++ case NETBACK_ACCEL_RES_HWINFO:
++ VPRINTK("Release hardware resources\n");
++ netback_accel_release_hwinfo(bend);
++ /* deliberate drop through */
++ case NETBACK_ACCEL_RES_FILTER:
++ VPRINTK("Free filters...\n");
++ netback_accel_filter_shutdown(bend);
++ /* deliberate drop through */
++ case NETBACK_ACCEL_RES_ALLOC:
++ VPRINTK("Free vnic...\n");
++ ef_free_vnic(bend);
++ /* deliberate drop through */
++ case NETBACK_ACCEL_RES_NONE:
++ break;
++ default:
++ BUG();
++ }
++}
++
++/**************************************************************************
++ *
++ * Buffer table stuff
++ *
++ **************************************************************************/
++
++/*
++ * Undo any allocation that netback_accel_msg_rx_buffer_map() has made
++ * if it fails half way through
++ */
++static inline void buffer_map_cleanup(struct netback_accel *bend, int i)
++{
++ while (i > 0) {
++ i--;
++ bend->buffer_maps_index--;
++ net_accel_unmap_device_page(bend->hdev_data,
++ bend->buffer_maps[bend->buffer_maps_index],
++ bend->buffer_addrs[bend->buffer_maps_index]);
++ }
++}
++
++
++int netback_accel_add_buffers(struct netback_accel *bend, int pages, int log2_pages,
++ u32 *grants, u32 *buf_addr_out)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++ unsigned long long addr_array[NET_ACCEL_MSG_MAX_PAGE_REQ];
++ int rc, i, index;
++ u64 dev_bus_addr;
++
++ /* Make sure we can't overflow the dma_maps array */
++ if (accel_hw_priv->dma_maps_index >=
++ bend->max_pages / NET_ACCEL_MSG_MAX_PAGE_REQ) {
++ EPRINTK("%s: too many buffer table allocations: %d %d\n",
++ __FUNCTION__, accel_hw_priv->dma_maps_index,
++ bend->max_pages / NET_ACCEL_MSG_MAX_PAGE_REQ);
++ return -EINVAL;
++ }
++
++ /* Make sure we can't overflow the buffer_maps array */
++ if (bend->buffer_maps_index + pages > bend->max_pages) {
++ EPRINTK("%s: too many pages mapped: %d + %d > %d\n",
++ __FUNCTION__, bend->buffer_maps_index,
++ pages, bend->max_pages);
++ return -EINVAL;
++ }
++
++ for (i = 0; i < pages; i++) {
++ VPRINTK("%s: mapping page %d\n", __FUNCTION__, i);
++ rc = net_accel_map_device_page
++ (bend->hdev_data, grants[i],
++ &bend->buffer_maps[bend->buffer_maps_index],
++ &dev_bus_addr);
++
++ if (rc != 0) {
++ EPRINTK("error in net_accel_map_device_page\n");
++ buffer_map_cleanup(bend, i);
++ return rc;
++ }
++
++ bend->buffer_addrs[bend->buffer_maps_index] = dev_bus_addr;
++
++ bend->buffer_maps_index++;
++
++ addr_array[i] = dev_bus_addr;
++ }
++
++ VPRINTK("%s: mapping dma addresses to vih %p\n", __FUNCTION__,
++ accel_hw_priv->efx_vih);
++
++ index = accel_hw_priv->dma_maps_index;
++ if ((rc = efx_vi_dma_map_addrs(accel_hw_priv->efx_vih, addr_array, pages,
++ &(accel_hw_priv->dma_maps[index]))) < 0) {
++ EPRINTK("error in dma_map_pages\n");
++ buffer_map_cleanup(bend, i);
++ return rc;
++ }
++
++ accel_hw_priv->dma_maps_index++;
++ NETBACK_ACCEL_STATS_OP(bend->stats.num_buffer_pages += pages);
++
++ //DPRINTK("%s: getting map address\n", __FUNCTION__);
++
++ *buf_addr_out = efx_vi_dma_get_map_addr(accel_hw_priv->efx_vih,
++ accel_hw_priv->dma_maps[index]);
++
++ //DPRINTK("%s: done\n", __FUNCTION__);
++
++ return 0;
++}
++
++
++int netback_accel_remove_buffers(struct netback_accel *bend)
++{
++ /* Only try to free buffers if accel_hw_priv was setup */
++ if (bend->hw_state != NETBACK_ACCEL_RES_NONE) {
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++ int i;
++
++ efx_vi_reset(accel_hw_priv->efx_vih);
++
++ while (accel_hw_priv->dma_maps_index > 0) {
++ accel_hw_priv->dma_maps_index--;
++ i = accel_hw_priv->dma_maps_index;
++ efx_vi_dma_unmap_addrs(accel_hw_priv->efx_vih,
++ accel_hw_priv->dma_maps[i]);
++ }
++
++ while (bend->buffer_maps_index > 0) {
++ VPRINTK("Unmapping granted buffer %d\n",
++ bend->buffer_maps_index);
++ bend->buffer_maps_index--;
++ i = bend->buffer_maps_index;
++ net_accel_unmap_device_page(bend->hdev_data,
++ bend->buffer_maps[i],
++ bend->buffer_addrs[i]);
++ }
++
++ NETBACK_ACCEL_STATS_OP(bend->stats.num_buffer_pages = 0);
++ }
++
++ return 0;
++}
++
++/**************************************************************************
++ *
++ * Filter stuff
++ *
++ **************************************************************************/
++
++static int netback_accel_filter_init(struct netback_accel *bend)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++ int i, rc;
++
++ BUG_ON(bend->hw_state != NETBACK_ACCEL_RES_ALLOC);
++
++ spin_lock_init(&accel_hw_priv->filter_lock);
++
++ if ((rc = cuckoo_hash_init(&accel_hw_priv->filter_hash_table,
++ 5 /* space for 32 filters */, 8)) != 0) {
++ EPRINTK("Failed to initialise filter hash table\n");
++ return rc;
++ }
++
++ accel_hw_priv->fspecs = kzalloc(sizeof(struct netback_accel_filter_spec) *
++ bend->quotas.max_filters,
++ GFP_KERNEL);
++
++ if (accel_hw_priv->fspecs == NULL) {
++ EPRINTK("No memory for filter specs.\n");
++ cuckoo_hash_destroy(&accel_hw_priv->filter_hash_table);
++ return -ENOMEM;
++ }
++
++ for (i = 0; i < bend->quotas.max_filters; i++) {
++ accel_hw_priv->free_filters |= (1 << i);
++ }
++
++ /* Base mask on highest set bit in max_filters */
++ accel_hw_priv->filter_idx_mask = (1 << fls(bend->quotas.max_filters)) - 1;
++ VPRINTK("filter setup: max is %x mask is %x\n",
++ bend->quotas.max_filters, accel_hw_priv->filter_idx_mask);
++
++ bend->hw_state = NETBACK_ACCEL_RES_FILTER;
++
++ return 0;
++}
++
++
++static inline void make_filter_key(cuckoo_hash_ip_key *key,
++ struct netback_accel_filter_spec *filt)
++
++{
++ key->local_ip = filt->destip_be;
++ key->local_port = filt->destport_be;
++ key->proto = filt->proto;
++}
++
++
++static inline
++void netback_accel_free_filter(struct falcon_bend_accel_priv *accel_hw_priv,
++ int filter)
++{
++ cuckoo_hash_ip_key filter_key;
++
++ if (!(accel_hw_priv->free_filters & (1 << filter))) {
++ efx_vi_filter_stop(accel_hw_priv->efx_vih,
++ accel_hw_priv->fspecs[filter].filter_handle);
++ make_filter_key(&filter_key, &(accel_hw_priv->fspecs[filter]));
++ if (cuckoo_hash_remove(&accel_hw_priv->filter_hash_table,
++ (cuckoo_hash_key *)&filter_key)) {
++ EPRINTK("%s: Couldn't find filter to remove from table\n",
++ __FUNCTION__);
++ BUG();
++ }
++ }
++}
++
++
++static void netback_accel_filter_shutdown(struct netback_accel *bend)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++ int i;
++ unsigned long flags;
++
++ BUG_ON(bend->hw_state != NETBACK_ACCEL_RES_FILTER);
++
++ spin_lock_irqsave(&accel_hw_priv->filter_lock, flags);
++
++ BUG_ON(accel_hw_priv->fspecs == NULL);
++
++ for (i = 0; i < bend->quotas.max_filters; i++) {
++ netback_accel_free_filter(accel_hw_priv, i);
++ }
++
++ kfree(accel_hw_priv->fspecs);
++ accel_hw_priv->fspecs = NULL;
++ accel_hw_priv->free_filters = 0;
++
++ cuckoo_hash_destroy(&accel_hw_priv->filter_hash_table);
++
++ spin_unlock_irqrestore(&accel_hw_priv->filter_lock, flags);
++
++ bend->hw_state = NETBACK_ACCEL_RES_ALLOC;
++}
++
++
++/*! Suggest a filter to replace when we want to insert a new one and have
++ * none free.
++ */
++static unsigned get_victim_filter(struct netback_accel *bend)
++{
++ /*
++ * We could attempt to get really clever, and may do at some
++ * point, but random replacement is v. cheap and low on
++ * pathological worst cases.
++ */
++ unsigned index, cycles;
++
++ rdtscl(cycles);
++
++ /*
++ * Some doubt about the quality of the bottom few bits, so
++ * throw 'em * away
++ */
++ index = (cycles >> 4) & ((struct falcon_bend_accel_priv *)
++ bend->accel_hw_priv)->filter_idx_mask;
++ /*
++ * We don't enforce that the number of filters is a power of
++ * two, but the masking gets us to within one subtraction of a
++ * valid index
++ */
++ if (index >= bend->quotas.max_filters)
++ index -= bend->quotas.max_filters;
++ DPRINTK("backend %s->%d has no free filters. Filter %d will be evicted\n",
++ bend->nicname, bend->far_end, index);
++ return index;
++}
++
++
++/* Add a filter for the specified IP/port to the backend */
++int
++netback_accel_filter_check_add(struct netback_accel *bend,
++ struct netback_accel_filter_spec *filt)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++ struct netback_accel_filter_spec *fs;
++ unsigned filter_index;
++ unsigned long flags;
++ int rc, recycling = 0;
++ cuckoo_hash_ip_key filter_key, evict_key;
++
++ BUG_ON(filt->proto != IPPROTO_TCP && filt->proto != IPPROTO_UDP);
++
++ DPRINTK("Will add %s filter for dst ip %08x and dst port %d\n",
++ (filt->proto == IPPROTO_TCP) ? "TCP" : "UDP",
++ be32_to_cpu(filt->destip_be), be16_to_cpu(filt->destport_be));
++
++ spin_lock_irqsave(&accel_hw_priv->filter_lock, flags);
++ /*
++ * Check to see if we're already filtering this IP address and
++ * port. Happens if you insert a filter mid-stream as there
++ * are many packets backed up to be delivered to dom0 already
++ */
++ make_filter_key(&filter_key, filt);
++ if (cuckoo_hash_lookup(&accel_hw_priv->filter_hash_table,
++ (cuckoo_hash_key *)(&filter_key),
++ &filter_index)) {
++ DPRINTK("Found matching filter %d already in table\n",
++ filter_index);
++ rc = -1;
++ goto out;
++ }
++
++ if (accel_hw_priv->free_filters == 0) {
++ filter_index = get_victim_filter(bend);
++ recycling = 1;
++ } else {
++ filter_index = __ffs(accel_hw_priv->free_filters);
++ clear_bit(filter_index, &accel_hw_priv->free_filters);
++ }
++
++ fs = &accel_hw_priv->fspecs[filter_index];
++
++ if (recycling) {
++ DPRINTK("Removing filter index %d handle %p\n", filter_index,
++ fs->filter_handle);
++
++ if ((rc = efx_vi_filter_stop(accel_hw_priv->efx_vih,
++ fs->filter_handle)) != 0) {
++ EPRINTK("Couldn't clear NIC filter table entry %d\n", rc);
++ }
++
++ make_filter_key(&evict_key, fs);
++ if (cuckoo_hash_remove(&accel_hw_priv->filter_hash_table,
++ (cuckoo_hash_key *)&evict_key)) {
++ EPRINTK("Couldn't find filter to remove from table\n");
++ BUG();
++ }
++ NETBACK_ACCEL_STATS_OP(bend->stats.num_filters--);
++ }
++
++ /* Update the filter spec with new details */
++ *fs = *filt;
++
++ if ((rc = cuckoo_hash_add(&accel_hw_priv->filter_hash_table,
++ (cuckoo_hash_key *)&filter_key, filter_index,
++ 1)) != 0) {
++ EPRINTK("Error (%d) adding filter to table\n", rc);
++ accel_hw_priv->free_filters |= (1 << filter_index);
++ goto out;
++ }
++
++ rc = efx_vi_filter(accel_hw_priv->efx_vih, filt->proto, filt->destip_be,
++ filt->destport_be,
++ (struct filter_resource_t **)&fs->filter_handle);
++
++ if (rc != 0) {
++ EPRINTK("Hardware filter insertion failed. Error %d\n", rc);
++ accel_hw_priv->free_filters |= (1 << filter_index);
++ cuckoo_hash_remove(&accel_hw_priv->filter_hash_table,
++ (cuckoo_hash_key *)&filter_key);
++ rc = -1;
++ goto out;
++ }
++
++ NETBACK_ACCEL_STATS_OP(bend->stats.num_filters++);
++
++ VPRINTK("%s: success index %d handle %p\n", __FUNCTION__, filter_index,
++ fs->filter_handle);
++
++ rc = filter_index;
++ out:
++ spin_unlock_irqrestore(&accel_hw_priv->filter_lock, flags);
++ return rc;
++}
++
++
++/* Remove a filter entry for the specific device and IP/port */
++static void netback_accel_filter_remove(struct netback_accel *bend,
++ int filter_index)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++
++ BUG_ON(accel_hw_priv->free_filters & (1 << filter_index));
++ netback_accel_free_filter(accel_hw_priv, filter_index);
++ accel_hw_priv->free_filters |= (1 << filter_index);
++}
++
++
++/* Remove a filter entry for the specific device and IP/port */
++void netback_accel_filter_remove_spec(struct netback_accel *bend,
++ struct netback_accel_filter_spec *filt)
++{
++ struct falcon_bend_accel_priv *accel_hw_priv = bend->accel_hw_priv;
++ unsigned filter_found;
++ unsigned long flags;
++ cuckoo_hash_ip_key filter_key;
++ struct netback_accel_filter_spec *fs;
++
++ if (filt->proto == IPPROTO_TCP) {
++ DPRINTK("Remove TCP filter for dst ip %08x and dst port %d\n",
++ be32_to_cpu(filt->destip_be),
++ be16_to_cpu(filt->destport_be));
++ } else if (filt->proto == IPPROTO_UDP) {
++ DPRINTK("Remove UDP filter for dst ip %08x and dst port %d\n",
++ be32_to_cpu(filt->destip_be),
++ be16_to_cpu(filt->destport_be));
++ } else {
++ /*
++ * This could be provoked by an evil frontend, so can't
++ * BUG(), but harmless as it should fail tests below
++ */
++ DPRINTK("Non-TCP/UDP filter dst ip %08x and dst port %d\n",
++ be32_to_cpu(filt->destip_be),
++ be16_to_cpu(filt->destport_be));
++ }
++
++ spin_lock_irqsave(&accel_hw_priv->filter_lock, flags);
++
++ make_filter_key(&filter_key, filt);
++ if (!cuckoo_hash_lookup(&accel_hw_priv->filter_hash_table,
++ (cuckoo_hash_key *)(&filter_key),
++ &filter_found)) {
++ EPRINTK("Couldn't find matching filter already in table\n");
++ goto out;
++ }
++
++ /* Do a full check to make sure we've not had a hash collision */
++ fs = &accel_hw_priv->fspecs[filter_found];
++ if (fs->destip_be == filt->destip_be &&
++ fs->destport_be == filt->destport_be &&
++ fs->proto == filt->proto &&
++ !memcmp(fs->mac, filt->mac, ETH_ALEN)) {
++ netback_accel_filter_remove(bend, filter_found);
++ } else {
++ EPRINTK("Entry in hash table does not match filter spec\n");
++ goto out;
++ }
++
++ out:
++ spin_unlock_irqrestore(&accel_hw_priv->filter_lock, flags);
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/accel_solarflare.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_solarflare.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/accel_solarflare.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_solarflare.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,88 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NETBACK_ACCEL_SOLARFLARE_H
++#define NETBACK_ACCEL_SOLARFLARE_H
++
++#include "accel.h"
++#include "accel_msg_iface.h"
++
++#include "driverlink_api.h"
++
++#define MAX_NICS 5
++#define MAX_PORTS 2
++
++
++extern int netback_accel_sf_init(void);
++extern void netback_accel_sf_shutdown(void);
++extern int netback_accel_sf_hwtype(struct netback_accel *bend);
++
++extern int netback_accel_sf_char_init(void);
++extern void netback_accel_sf_char_shutdown(void);
++
++extern int netback_accel_setup_vnic_hw(struct netback_accel *bend);
++extern void netback_accel_shutdown_vnic_hw(struct netback_accel *bend);
++
++extern int netback_accel_add_buffers(struct netback_accel *bend, int pages,
++ int log2_pages, u32 *grants,
++ u32 *buf_addr_out);
++extern int netback_accel_remove_buffers(struct netback_accel *bend);
++
++
++/* Add a filter for the specified IP/port to the backend */
++extern int
++netback_accel_filter_check_add(struct netback_accel *bend,
++ struct netback_accel_filter_spec *filt);
++/* Remove a filter entry for the specific device and IP/port */
++extern
++void netback_accel_filter_remove_index(struct netback_accel *bend,
++ int filter_index);
++extern
++void netback_accel_filter_remove_spec(struct netback_accel *bend,
++ struct netback_accel_filter_spec *filt);
++
++/* This is designed to look a bit like a skb */
++struct netback_pkt_buf {
++ union {
++ unsigned char *raw;
++ } mac;
++ union {
++ struct iphdr *iph;
++ struct arphdr *arph;
++ unsigned char *raw;
++ } nh;
++ int protocol;
++};
++
++/*! \brief Handle a received packet: insert fast path filters as necessary
++ * \param skb The packet buffer
++ */
++extern void netback_accel_rx_packet(struct netback_pkt_buf *skb, void *fwd_priv);
++
++/*! \brief Handle a transmitted packet: update fast path filters as necessary
++ * \param skb The packet buffer
++ */
++extern void netback_accel_tx_packet(struct sk_buff *skb, void *fwd_priv);
++
++#endif /* NETBACK_ACCEL_SOLARFLARE_H */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/accel_xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_xenbus.c
+--- linux-2.6.18.8/drivers/xen/sfc_netback/accel_xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/accel_xenbus.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,831 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <xen/evtchn.h>
++#include <linux/mutex.h>
++
++/* drivers/xen/netback/common.h */
++#include "common.h"
++
++#include "accel.h"
++#include "accel_solarflare.h"
++#include "accel_util.h"
++
++#define NODENAME_PATH_FMT "backend/vif/%d/%d"
++
++#define NETBACK_ACCEL_FROM_XENBUS_DEVICE(_dev) (struct netback_accel *) \
++ ((struct backend_info *)(_dev)->dev.driver_data)->netback_accel_priv
++
++/* List of all the bends currently in existence. */
++struct netback_accel *bend_list = NULL;
++DEFINE_MUTEX(bend_list_mutex);
++
++/* Put in bend_list. Must hold bend_list_mutex */
++static void link_bend(struct netback_accel *bend)
++{
++ bend->next_bend = bend_list;
++ bend_list = bend;
++}
++
++/* Remove from bend_list, Must hold bend_list_mutex */
++static void unlink_bend(struct netback_accel *bend)
++{
++ struct netback_accel *tmp = bend_list;
++ struct netback_accel *prev = NULL;
++ while (tmp != NULL) {
++ if (tmp == bend) {
++ if (prev != NULL)
++ prev->next_bend = bend->next_bend;
++ else
++ bend_list = bend->next_bend;
++ return;
++ }
++ prev = tmp;
++ tmp = tmp->next_bend;
++ }
++}
++
++
++/* Demultiplex a message IRQ from the frontend driver. */
++static irqreturn_t msgirq_from_frontend(int irq, void *context,
++ struct pt_regs *unused)
++{
++ struct xenbus_device *dev = context;
++ struct netback_accel *bend = NETBACK_ACCEL_FROM_XENBUS_DEVICE(dev);
++ VPRINTK("irq %d from device %s\n", irq, dev->nodename);
++ schedule_work(&bend->handle_msg);
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * Demultiplex an IRQ from the frontend driver. This is never used
++ * functionally, but we need it to pass to the bind function, and may
++ * get called spuriously
++ */
++static irqreturn_t netirq_from_frontend(int irq, void *context,
++ struct pt_regs *unused)
++{
++ VPRINTK("netirq %d from device %s\n", irq,
++ ((struct xenbus_device *)context)->nodename);
++
++ return IRQ_HANDLED;
++}
++
++
++/* Read the limits values of the xenbus structure. */
++static
++void cfg_hw_quotas(struct xenbus_device *dev, struct netback_accel *bend)
++{
++ int err = xenbus_gather
++ (XBT_NIL, dev->nodename,
++ "limits/max-filters", "%d", &bend->quotas.max_filters,
++ "limits/max-buf-pages", "%d", &bend->quotas.max_buf_pages,
++ "limits/max-mcasts", "%d", &bend->quotas.max_mcasts,
++ NULL);
++ if (err) {
++ /*
++ * TODO what if they have previously been set by the
++ * user? This will overwrite with defaults. Maybe
++ * not what we want to do, but useful in startup
++ * case
++ */
++ DPRINTK("Failed to read quotas from xenbus, using defaults\n");
++ bend->quotas.max_filters = NETBACK_ACCEL_DEFAULT_MAX_FILTERS;
++ bend->quotas.max_buf_pages = sfc_netback_max_pages;
++ bend->quotas.max_mcasts = NETBACK_ACCEL_DEFAULT_MAX_MCASTS;
++ }
++
++ return;
++}
++
++
++static void bend_config_accel_change(struct xenbus_watch *watch,
++ const char **vec, unsigned int len)
++{
++ struct netback_accel *bend;
++
++ bend = container_of(watch, struct netback_accel, config_accel_watch);
++
++ mutex_lock(&bend->bend_mutex);
++ if (bend->config_accel_watch.node != NULL) {
++ struct xenbus_device *dev =
++ (struct xenbus_device *)bend->hdev_data;
++ DPRINTK("Watch matched, got dev %p otherend %p\n",
++ dev, dev->otherend);
++ if(!xenbus_exists(XBT_NIL, watch->node, "")) {
++ DPRINTK("Ignoring watch as otherend seems invalid\n");
++ goto out;
++ }
++
++ cfg_hw_quotas(dev, bend);
++ }
++ out:
++ mutex_unlock(&bend->bend_mutex);
++ return;
++}
++
++
++/*
++ * Setup watch on "limits" in the backend vif info to know when
++ * configuration has been set
++ */
++static int setup_config_accel_watch(struct xenbus_device *dev,
++ struct netback_accel *bend)
++{
++ int err;
++
++ VPRINTK("Setting watch on %s/%s\n", dev->nodename, "limits");
++
++ err = xenbus_watch_path2(dev, dev->nodename, "limits",
++ &bend->config_accel_watch,
++ bend_config_accel_change);
++
++ if (err) {
++ EPRINTK("%s: Failed to register xenbus watch: %d\n",
++ __FUNCTION__, err);
++ bend->config_accel_watch.node = NULL;
++ return err;
++ }
++ return 0;
++}
++
++
++static int
++cfg_frontend_info(struct xenbus_device *dev, struct netback_accel *bend,
++ int *grants)
++{
++ /* Get some info from xenbus on the event channel and shmem grant */
++ int err = xenbus_gather(XBT_NIL, dev->otherend,
++ "accel-msg-channel", "%u", &bend->msg_channel,
++ "accel-ctrl-page", "%d", &(grants[0]),
++ "accel-msg-page", "%d", &(grants[1]),
++ "accel-net-channel", "%u", &bend->net_channel,
++ NULL);
++ if (err)
++ EPRINTK("failed to read event channels or shmem grant: %d\n",
++ err);
++ else
++ DPRINTK("got event chan %d and net chan %d from frontend\n",
++ bend->msg_channel, bend->net_channel);
++ return err;
++}
++
++
++/* Setup all the comms needed to chat with the front end driver */
++static int setup_vnic(struct xenbus_device *dev)
++{
++ struct netback_accel *bend;
++ int grants[2], err, msgs_per_queue;
++
++ bend = NETBACK_ACCEL_FROM_XENBUS_DEVICE(dev);
++
++ err = cfg_frontend_info(dev, bend, grants);
++ if (err)
++ goto fail1;
++
++ /*
++ * If we get here, both frontend Connected and configuration
++ * options available. All is well.
++ */
++
++ /* Get the hardware quotas for the VNIC in question. */
++ cfg_hw_quotas(dev, bend);
++
++ /* Set up the deferred work handlers */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ INIT_WORK(&bend->handle_msg,
++ netback_accel_msg_rx_handler);
++#else
++ INIT_WORK(&bend->handle_msg,
++ netback_accel_msg_rx_handler,
++ (void*)bend);
++#endif
++
++ /* Request the frontend mac */
++ err = net_accel_xen_net_read_mac(dev, bend->mac);
++ if (err)
++ goto fail2;
++
++ /* Set up the shared page. */
++ bend->shared_page = net_accel_map_grants_contig(dev, grants, 2,
++ &bend->sh_pages_unmap);
++
++ if (bend->shared_page == NULL) {
++ EPRINTK("failed to map shared page for %s\n", dev->otherend);
++ err = -ENOMEM;
++ goto fail2;
++ }
++
++ /* Initialise the shared page(s) used for comms */
++ net_accel_msg_init_page(bend->shared_page, PAGE_SIZE,
++ bend->net_dev->flags & IFF_UP);
++
++ msgs_per_queue = (PAGE_SIZE/2) / sizeof(struct net_accel_msg);
++
++ net_accel_msg_init_queue
++ (&bend->to_domU, &bend->shared_page->queue0,
++ (struct net_accel_msg *)((__u8*)bend->shared_page + PAGE_SIZE),
++ msgs_per_queue);
++
++ net_accel_msg_init_queue
++ (&bend->from_domU, &bend->shared_page->queue1,
++ (struct net_accel_msg *)((__u8*)bend->shared_page +
++ (3 * PAGE_SIZE / 2)),
++ msgs_per_queue);
++
++ /* Bind the message event channel to a handler
++ *
++ * Note that we will probably get a spurious interrupt when we
++ * do this, so it must not be done until we have set up
++ * everything we need to handle it.
++ */
++ err = bind_interdomain_evtchn_to_irqhandler(dev->otherend_id,
++ bend->msg_channel,
++ msgirq_from_frontend,
++ 0,
++ "netback_accel",
++ dev);
++ if (err < 0) {
++ EPRINTK("failed to bind event channel: %d\n", err);
++ goto fail3;
++ }
++ else
++ bend->msg_channel_irq = err;
++
++ /* TODO: No need to bind this evtchn to an irq. */
++ err = bind_interdomain_evtchn_to_irqhandler(dev->otherend_id,
++ bend->net_channel,
++ netirq_from_frontend,
++ 0,
++ "netback_accel",
++ dev);
++ if (err < 0) {
++ EPRINTK("failed to bind net channel: %d\n", err);
++ goto fail4;
++ }
++ else
++ bend->net_channel_irq = err;
++
++ /*
++ * Grab ourselves an entry in the forwarding hash table. We do
++ * this now so we don't have the embarassmesnt of sorting out
++ * an allocation failure while at IRQ. Because we pass NULL as
++ * the context, the actual hash lookup will succeed for this
++ * NIC, but the check for somewhere to forward to will
++ * fail. This is necessary to prevent forwarding before
++ * hardware resources are set up
++ */
++ err = netback_accel_fwd_add(bend->mac, NULL, bend->fwd_priv);
++ if (err) {
++ EPRINTK("failed to add to fwd hash table\n");
++ goto fail5;
++ }
++
++ /*
++ * Say hello to frontend. Important to do this straight after
++ * obtaining the message queue as otherwise we are vulnerable
++ * to an evil frontend sending a HELLO-REPLY before we've sent
++ * the HELLO and confusing us
++ */
++ netback_accel_msg_tx_hello(bend, NET_ACCEL_MSG_VERSION);
++ return 0;
++
++ fail5:
++ unbind_from_irqhandler(bend->net_channel_irq, dev);
++ fail4:
++ unbind_from_irqhandler(bend->msg_channel_irq, dev);
++ fail3:
++ net_accel_unmap_grants_contig(dev, bend->sh_pages_unmap);
++ bend->shared_page = NULL;
++ bend->sh_pages_unmap = NULL;
++ fail2:
++ fail1:
++ return err;
++}
++
++
++static int read_nicname(struct xenbus_device *dev, struct netback_accel *bend)
++{
++ int len;
++
++ /* nic name used to select interface used for acceleration */
++ bend->nicname = xenbus_read(XBT_NIL, dev->nodename, "accel", &len);
++ if (IS_ERR(bend->nicname))
++ return PTR_ERR(bend->nicname);
++
++ return 0;
++}
++
++static const char *frontend_name = "sfc_netfront";
++
++static int publish_frontend_name(struct xenbus_device *dev)
++{
++ struct xenbus_transaction tr;
++ int err;
++
++ /* Publish the name of the frontend driver */
++ do {
++ err = xenbus_transaction_start(&tr);
++ if (err != 0) {
++ EPRINTK("%s: transaction start failed\n", __FUNCTION__);
++ return err;
++ }
++ err = xenbus_printf(tr, dev->nodename, "accel-frontend",
++ "%s", frontend_name);
++ if (err != 0) {
++ EPRINTK("%s: xenbus_printf failed\n", __FUNCTION__);
++ xenbus_transaction_end(tr, 1);
++ return err;
++ }
++ err = xenbus_transaction_end(tr, 0);
++ } while (err == -EAGAIN);
++
++ if (err != 0) {
++ EPRINTK("failed to end frontend name transaction\n");
++ return err;
++ }
++ return 0;
++}
++
++
++static int unpublish_frontend_name(struct xenbus_device *dev)
++{
++ struct xenbus_transaction tr;
++ int err;
++
++ do {
++ err = xenbus_transaction_start(&tr);
++ if (err != 0)
++ break;
++ err = xenbus_rm(tr, dev->nodename, "accel-frontend");
++ if (err != 0) {
++ xenbus_transaction_end(tr, 1);
++ break;
++ }
++ err = xenbus_transaction_end(tr, 0);
++ } while (err == -EAGAIN);
++
++ return err;
++}
++
++
++static void cleanup_vnic(struct netback_accel *bend)
++{
++ struct xenbus_device *dev;
++
++ dev = (struct xenbus_device *)bend->hdev_data;
++
++ DPRINTK("%s: bend %p dev %p\n", __FUNCTION__, bend, dev);
++
++ DPRINTK("%s: Remove %p's mac from fwd table...\n",
++ __FUNCTION__, bend);
++ netback_accel_fwd_remove(bend->mac, bend->fwd_priv);
++
++ /* Free buffer table allocations */
++ netback_accel_remove_buffers(bend);
++
++ DPRINTK("%s: Release hardware resources...\n", __FUNCTION__);
++ if (bend->accel_shutdown)
++ bend->accel_shutdown(bend);
++
++ if (bend->net_channel_irq) {
++ unbind_from_irqhandler(bend->net_channel_irq, dev);
++ bend->net_channel_irq = 0;
++ }
++
++ if (bend->msg_channel_irq) {
++ unbind_from_irqhandler(bend->msg_channel_irq, dev);
++ bend->msg_channel_irq = 0;
++ }
++
++ if (bend->sh_pages_unmap) {
++ DPRINTK("%s: Unmap grants %p\n", __FUNCTION__,
++ bend->sh_pages_unmap);
++ net_accel_unmap_grants_contig(dev, bend->sh_pages_unmap);
++ bend->sh_pages_unmap = NULL;
++ bend->shared_page = NULL;
++ }
++}
++
++
++/*************************************************************************/
++
++/*
++ * The following code handles accelstate changes between the frontend
++ * and the backend. It calls setup_vnic and cleanup_vnic in matching
++ * pairs in response to transitions.
++ *
++ * Valid state transitions for Dom0 are as follows:
++ *
++ * Closed->Init on probe or in response to Init from domU
++ * Closed->Closing on error/remove
++ *
++ * Init->Connected in response to Connected from domU
++ * Init->Closing on error/remove or in response to Closing from domU
++ *
++ * Connected->Closing on error/remove or in response to Closing from domU
++ *
++ * Closing->Closed in response to Closed from domU
++ *
++ */
++
++
++static void netback_accel_frontend_changed(struct xenbus_device *dev,
++ XenbusState frontend_state)
++{
++ struct netback_accel *bend = NETBACK_ACCEL_FROM_XENBUS_DEVICE(dev);
++ XenbusState backend_state;
++
++ DPRINTK("%s: changing from %s to %s. nodename %s, otherend %s\n",
++ __FUNCTION__, xenbus_strstate(bend->frontend_state),
++ xenbus_strstate(frontend_state),dev->nodename, dev->otherend);
++
++ /*
++ * Ignore duplicate state changes. This can happen if the
++ * frontend changes state twice in quick succession and the
++ * first watch fires in the backend after the second
++ * transition has completed.
++ */
++ if (bend->frontend_state == frontend_state)
++ return;
++
++ bend->frontend_state = frontend_state;
++ backend_state = bend->backend_state;
++
++ switch (frontend_state) {
++ case XenbusStateInitialising:
++ if (backend_state == XenbusStateClosed &&
++ !bend->removing)
++ backend_state = XenbusStateInitialising;
++ break;
++
++ case XenbusStateConnected:
++ if (backend_state == XenbusStateInitialising) {
++ if (!bend->vnic_is_setup &&
++ setup_vnic(dev) == 0) {
++ bend->vnic_is_setup = 1;
++ backend_state = XenbusStateConnected;
++ } else {
++ backend_state = XenbusStateClosing;
++ }
++ }
++ break;
++
++ case XenbusStateInitWait:
++ case XenbusStateInitialised:
++ default:
++ DPRINTK("Unknown state %s (%d) from frontend.\n",
++ xenbus_strstate(frontend_state), frontend_state);
++ /* Unknown state. Fall through. */
++ case XenbusStateClosing:
++ if (backend_state != XenbusStateClosed)
++ backend_state = XenbusStateClosing;
++
++ /*
++ * The bend will now persist (with watches active) in
++ * case the frontend comes back again, eg. after
++ * frontend module reload or suspend/resume
++ */
++
++ break;
++
++ case XenbusStateUnknown:
++ case XenbusStateClosed:
++ if (bend->vnic_is_setup) {
++ bend->vnic_is_setup = 0;
++ cleanup_vnic(bend);
++ }
++
++ if (backend_state == XenbusStateClosing)
++ backend_state = XenbusStateClosed;
++ break;
++ }
++
++ if (backend_state != bend->backend_state) {
++ DPRINTK("Switching from state %s (%d) to %s (%d)\n",
++ xenbus_strstate(bend->backend_state),
++ bend->backend_state,
++ xenbus_strstate(backend_state), backend_state);
++ bend->backend_state = backend_state;
++ net_accel_update_state(dev, backend_state);
++ }
++
++ wake_up(&bend->state_wait_queue);
++}
++
++
++/* accelstate on the frontend's xenbus node has changed */
++static void bend_domu_accel_change(struct xenbus_watch *watch,
++ const char **vec, unsigned int len)
++{
++ int state;
++ struct netback_accel *bend;
++
++ bend = container_of(watch, struct netback_accel, domu_accel_watch);
++ if (bend->domu_accel_watch.node != NULL) {
++ struct xenbus_device *dev =
++ (struct xenbus_device *)bend->hdev_data;
++ VPRINTK("Watch matched, got dev %p otherend %p\n",
++ dev, dev->otherend);
++ /*
++ * dev->otherend != NULL check to protect against
++ * watch firing when domain goes away and we haven't
++ * yet cleaned up
++ */
++ if (!dev->otherend ||
++ !xenbus_exists(XBT_NIL, watch->node, "") ||
++ strncmp(dev->otherend, vec[XS_WATCH_PATH],
++ strlen(dev->otherend))) {
++ DPRINTK("Ignoring watch as otherend seems invalid\n");
++ return;
++ }
++
++ mutex_lock(&bend->bend_mutex);
++
++ xenbus_scanf(XBT_NIL, dev->otherend, "accelstate", "%d",
++ &state);
++ netback_accel_frontend_changed(dev, state);
++
++ mutex_unlock(&bend->bend_mutex);
++ }
++}
++
++/* Setup watch on frontend's accelstate */
++static int setup_domu_accel_watch(struct xenbus_device *dev,
++ struct netback_accel *bend)
++{
++ int err;
++
++ VPRINTK("Setting watch on %s/%s\n", dev->otherend, "accelstate");
++
++ err = xenbus_watch_path2(dev, dev->otherend, "accelstate",
++ &bend->domu_accel_watch,
++ bend_domu_accel_change);
++ if (err) {
++ EPRINTK("%s: Failed to register xenbus watch: %d\n",
++ __FUNCTION__, err);
++ goto fail;
++ }
++ return 0;
++ fail:
++ bend->domu_accel_watch.node = NULL;
++ return err;
++}
++
++
++int netback_accel_probe(struct xenbus_device *dev)
++{
++ struct netback_accel *bend;
++ struct backend_info *binfo;
++ int err;
++
++ DPRINTK("%s: passed device %s\n", __FUNCTION__, dev->nodename);
++
++ /* Allocate structure to store all our state... */
++ bend = kzalloc(sizeof(struct netback_accel), GFP_KERNEL);
++ if (bend == NULL) {
++ DPRINTK("%s: no memory for bend\n", __FUNCTION__);
++ return -ENOMEM;
++ }
++
++ mutex_init(&bend->bend_mutex);
++
++ mutex_lock(&bend->bend_mutex);
++
++ /* ...and store it where we can get at it */
++ binfo = (struct backend_info *) dev->dev.driver_data;
++ binfo->netback_accel_priv = bend;
++ /* And vice-versa */
++ bend->hdev_data = dev;
++
++ DPRINTK("%s: Adding bend %p to list\n", __FUNCTION__, bend);
++
++ init_waitqueue_head(&bend->state_wait_queue);
++ bend->vnic_is_setup = 0;
++ bend->frontend_state = XenbusStateUnknown;
++ bend->backend_state = XenbusStateClosed;
++ bend->removing = 0;
++
++ sscanf(dev->nodename, NODENAME_PATH_FMT, &bend->far_end,
++ &bend->vif_num);
++
++ err = read_nicname(dev, bend);
++ if (err) {
++ /*
++ * Technically not an error, just means we're not
++ * supposed to accelerate this
++ */
++ DPRINTK("failed to get device name\n");
++ goto fail_nicname;
++ }
++
++ /*
++ * Look up the device name in the list of NICs provided by
++ * driverlink to get the hardware type.
++ */
++ err = netback_accel_sf_hwtype(bend);
++ if (err) {
++ /*
++ * Technically not an error, just means we're not
++ * supposed to accelerate this, probably belongs to
++ * some other backend
++ */
++ DPRINTK("failed to match device name\n");
++ goto fail_init_type;
++ }
++
++ err = publish_frontend_name(dev);
++ if (err)
++ goto fail_publish;
++
++ err = netback_accel_debugfs_create(bend);
++ if (err)
++ goto fail_debugfs;
++
++ mutex_unlock(&bend->bend_mutex);
++
++ err = setup_config_accel_watch(dev, bend);
++ if (err)
++ goto fail_config_watch;
++
++ err = setup_domu_accel_watch(dev, bend);
++ if (err)
++ goto fail_domu_watch;
++
++ /*
++ * Indicate to the other end that we're ready to start unless
++ * the watch has already fired.
++ */
++ mutex_lock(&bend->bend_mutex);
++ if (bend->backend_state == XenbusStateClosed) {
++ bend->backend_state = XenbusStateInitialising;
++ net_accel_update_state(dev, XenbusStateInitialising);
++ }
++ mutex_unlock(&bend->bend_mutex);
++
++ mutex_lock(&bend_list_mutex);
++ link_bend(bend);
++ mutex_unlock(&bend_list_mutex);
++
++ return 0;
++
++fail_domu_watch:
++
++ unregister_xenbus_watch(&bend->config_accel_watch);
++ kfree(bend->config_accel_watch.node);
++fail_config_watch:
++
++ /*
++ * Flush the scheduled work queue before freeing bend to get
++ * rid of any pending netback_accel_msg_rx_handler()
++ */
++ flush_scheduled_work();
++
++ mutex_lock(&bend->bend_mutex);
++ net_accel_update_state(dev, XenbusStateUnknown);
++ netback_accel_debugfs_remove(bend);
++fail_debugfs:
++
++ unpublish_frontend_name(dev);
++fail_publish:
++
++ /* No need to reverse netback_accel_sf_hwtype. */
++fail_init_type:
++
++ kfree(bend->nicname);
++fail_nicname:
++ binfo->netback_accel_priv = NULL;
++ mutex_unlock(&bend->bend_mutex);
++ kfree(bend);
++ return err;
++}
++
++
++int netback_accel_remove(struct xenbus_device *dev)
++{
++ struct backend_info *binfo;
++ struct netback_accel *bend;
++ int frontend_state;
++
++ binfo = (struct backend_info *) dev->dev.driver_data;
++ bend = (struct netback_accel *) binfo->netback_accel_priv;
++
++ DPRINTK("%s: dev %p bend %p\n", __FUNCTION__, dev, bend);
++
++ BUG_ON(bend == NULL);
++
++ mutex_lock(&bend_list_mutex);
++ unlink_bend(bend);
++ mutex_unlock(&bend_list_mutex);
++
++ mutex_lock(&bend->bend_mutex);
++
++ /* Reject any requests to connect. */
++ bend->removing = 1;
++
++ /*
++ * Switch to closing to tell the other end that we're going
++ * away.
++ */
++ if (bend->backend_state != XenbusStateClosing) {
++ bend->backend_state = XenbusStateClosing;
++ net_accel_update_state(dev, XenbusStateClosing);
++ }
++
++ frontend_state = (int)XenbusStateUnknown;
++ xenbus_scanf(XBT_NIL, dev->otherend, "accelstate", "%d",
++ &frontend_state);
++
++ mutex_unlock(&bend->bend_mutex);
++
++ /*
++ * Wait until this end goes to the closed state. This happens
++ * in response to the other end going to the closed state.
++ * Don't bother doing this if the other end is already closed
++ * because if it is then there is nothing to do.
++ */
++ if (frontend_state != (int)XenbusStateClosed &&
++ frontend_state != (int)XenbusStateUnknown)
++ wait_event(bend->state_wait_queue,
++ bend->backend_state == XenbusStateClosed);
++
++ unregister_xenbus_watch(&bend->domu_accel_watch);
++ kfree(bend->domu_accel_watch.node);
++
++ unregister_xenbus_watch(&bend->config_accel_watch);
++ kfree(bend->config_accel_watch.node);
++
++ /*
++ * Flush the scheduled work queue before freeing bend to get
++ * rid of any pending netback_accel_msg_rx_handler()
++ */
++ flush_scheduled_work();
++
++ mutex_lock(&bend->bend_mutex);
++
++ /* Tear down the vnic if it was set up. */
++ if (bend->vnic_is_setup) {
++ bend->vnic_is_setup = 0;
++ cleanup_vnic(bend);
++ }
++
++ bend->backend_state = XenbusStateUnknown;
++ net_accel_update_state(dev, XenbusStateUnknown);
++
++ netback_accel_debugfs_remove(bend);
++
++ unpublish_frontend_name(dev);
++
++ kfree(bend->nicname);
++
++ binfo->netback_accel_priv = NULL;
++
++ mutex_unlock(&bend->bend_mutex);
++
++ kfree(bend);
++
++ return 0;
++}
++
++
++void netback_accel_shutdown_bends(void)
++{
++ mutex_lock(&bend_list_mutex);
++ /*
++ * I think we should have had a remove callback for all
++ * interfaces before being allowed to unload the module
++ */
++ BUG_ON(bend_list != NULL);
++ mutex_unlock(&bend_list_mutex);
++}
++
++
++void netback_accel_set_closing(struct netback_accel *bend)
++{
++
++ bend->backend_state = XenbusStateClosing;
++ net_accel_update_state((struct xenbus_device *)bend->hdev_data,
++ XenbusStateClosing);
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/gcc.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/gcc.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/gcc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/gcc.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,158 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*! \cidoxg_include_ci_compat */
++
++#ifndef __CI_COMPAT_GCC_H__
++#define __CI_COMPAT_GCC_H__
++
++
++#define CI_HAVE_INT64
++
++
++#if defined(__linux__) && defined(__KERNEL__)
++
++# include <linux/types.h>
++
++typedef __u64 ci_uint64;
++typedef __s64 ci_int64;
++# if BITS_PER_LONG == 32
++typedef __s32 ci_ptr_arith_t;
++typedef __u32 ci_uintptr_t;
++# else
++typedef __s64 ci_ptr_arith_t;
++typedef __u64 ci_uintptr_t;
++# endif
++
++
++/* it's not obvious to me why the below is wrong for x64_64, but
++ * gcc seems to complain on this platform
++ */
++# if defined(__ia64__)
++# define CI_PRId64 "ld"
++# define CI_PRIi64 "li"
++# define CI_PRIo64 "lo"
++# define CI_PRIu64 "lu"
++# define CI_PRIx64 "lx"
++# define CI_PRIX64 "lX"
++# else
++# define CI_PRId64 "lld"
++# define CI_PRIi64 "lli"
++# define CI_PRIo64 "llo"
++# define CI_PRIu64 "llu"
++# define CI_PRIx64 "llx"
++# define CI_PRIX64 "llX"
++# endif
++
++# define CI_PRId32 "d"
++# define CI_PRIi32 "i"
++# define CI_PRIo32 "o"
++# define CI_PRIu32 "u"
++# define CI_PRIx32 "x"
++# define CI_PRIX32 "X"
++
++#else
++
++# include <stdint.h>
++# include <inttypes.h>
++
++typedef uint64_t ci_uint64;
++typedef int64_t ci_int64;
++typedef intptr_t ci_ptr_arith_t;
++typedef uintptr_t ci_uintptr_t;
++
++# define CI_PRId64 PRId64
++# define CI_PRIi64 PRIi64
++# define CI_PRIo64 PRIo64
++# define CI_PRIu64 PRIu64
++# define CI_PRIx64 PRIx64
++# define CI_PRIX64 PRIX64
++
++# define CI_PRId32 PRId32
++# define CI_PRIi32 PRIi32
++# define CI_PRIo32 PRIo32
++# define CI_PRIu32 PRIu32
++# define CI_PRIx32 PRIx32
++# define CI_PRIX32 PRIX32
++
++#endif
++
++
++typedef ci_uint64 ci_fixed_descriptor_t;
++
++#define from_fixed_descriptor(desc) ((ci_uintptr_t)(desc))
++#define to_fixed_descriptor(desc) ((ci_fixed_descriptor_t)(ci_uintptr_t)(desc))
++
++
++#if __GNUC__ >= 3 && !defined(__cplusplus)
++/*
++** Checks that [p_mbr] has the same type as [&c_type::mbr_name].
++*/
++# define CI_CONTAINER(c_type, mbr_name, p_mbr) \
++ __builtin_choose_expr( \
++ __builtin_types_compatible_p(__typeof__(&((c_type*)0)->mbr_name), \
++ __typeof__(p_mbr)), \
++ __CI_CONTAINER(c_type, mbr_name, p_mbr), (void)0)
++
++# define ci_restrict __restrict__
++#endif
++
++
++#if !defined(__KERNEL__) || defined(__unix__)
++#define CI_HAVE_NPRINTF 1
++#endif
++
++
++/* At what version was this introduced? */
++#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ > 91)
++# define CI_LIKELY(t) __builtin_expect((t), 1)
++# define CI_UNLIKELY(t) __builtin_expect((t), 0)
++#endif
++
++/**********************************************************************
++ * Attributes
++ */
++#if __GNUC__ >= 3 && defined(NDEBUG)
++# define CI_HF __attribute__((visibility("hidden")))
++# define CI_HV __attribute__((visibility("hidden")))
++#else
++# define CI_HF
++# define CI_HV
++#endif
++
++#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
++# define ci_noinline static __attribute__((__noinline__))
++/* (Linux 2.6 defines its own "noinline", so we use the "__noinline__" form) */
++#else
++# define ci_noinline static
++#endif
++
++#define CI_ALIGN(x) __attribute__ ((aligned (x)))
++
++#define CI_PRINTF_LIKE(a,b) __attribute__((format(printf,a,b)))
++
++#endif /* __CI_COMPAT_GCC_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/gcc_x86.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/gcc_x86.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/gcc_x86.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/gcc_x86.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,115 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*! \cidoxg_include_ci_compat */
++
++#ifndef __CI_COMPAT_GCC_X86_H__
++#define __CI_COMPAT_GCC_X86_H__
++
++/*
++** The facts:
++**
++** SSE sfence
++** SSE2 lfence, mfence, pause
++*/
++
++/*
++ Barriers to enforce ordering with respect to:
++
++ normal memory use: ci_wmb, ci_rmb, ci_wmb
++ IO bus access use: ci_wiob, ci_riob, ci_iob
++*/
++#if defined(__x86_64__)
++# define ci_x86_mb() __asm__ __volatile__ ("lock; addl $0,0(%%rsp)":::"memory")
++#else
++# define ci_x86_mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)":::"memory")
++#endif
++
++/* ?? measure the impact of latency of sfence on a modern processor before we
++ take a decision on how to integrate with respect to writecombining */
++
++/* DJR: I don't think we need to add "memory" here. It means the asm does
++** something to memory that GCC doesn't understand. But all this does is
++** commit changes that GCC thinks have already happened. NB. GCC will not
++** reorder across a __volatile__ __asm__ anyway.
++*/
++#define ci_gcc_fence() __asm__ __volatile__ ("")
++
++#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
++# define ci_x86_sfence() __asm__ __volatile__ ("sfence")
++# define ci_x86_lfence() __asm__ __volatile__ ("lfence")
++# define ci_x86_mfence() __asm__ __volatile__ ("mfence")
++#else
++# define ci_x86_sfence() __asm__ __volatile__ (".byte 0x0F, 0xAE, 0xF8")
++# define ci_x86_lfence() __asm__ __volatile__ (".byte 0x0F, 0xAE, 0xE8")
++# define ci_x86_mfence() __asm__ __volatile__ (".byte 0x0F, 0xAE, 0xF0")
++#endif
++
++
++/* x86 processors to P4 Xeon store in-order unless executing streaming
++ extensions or when using writecombining
++
++ Hence we do not define ci_wmb to use sfence by default. Requirement is that
++ we do not use writecombining to memory and any code which uses SSE
++ extensions must call sfence directly
++
++ We need to track non intel clones which may support out of order store.
++
++*/
++
++#if CI_CPU_OOS
++# if CI_CPU_HAS_SSE
++# define ci_wmb() ci_x86_sfence()
++# else
++# define ci_wmb() ci_x86_mb()
++# endif
++#else
++# define ci_wmb() ci_gcc_fence()
++#endif
++
++#if CI_CPU_HAS_SSE2
++# define ci_rmb() ci_x86_lfence()
++# define ci_mb() ci_x86_mfence()
++# define ci_riob() ci_x86_lfence()
++# define ci_wiob() ci_x86_sfence()
++# define ci_iob() ci_x86_mfence()
++#else
++# if CI_CPU_HAS_SSE
++# define ci_wiob() ci_x86_sfence()
++# else
++# define ci_wiob() ci_x86_mb()
++# endif
++# define ci_rmb() ci_x86_mb()
++# define ci_mb() ci_x86_mb()
++# define ci_riob() ci_x86_mb()
++# define ci_iob() ci_x86_mb()
++#endif
++
++typedef unsigned long ci_phys_addr_t;
++#define ci_phys_addr_fmt "%lx"
++
++#endif /* __CI_COMPAT_GCC_X86_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/primitive.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/primitive.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/primitive.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/primitive.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,77 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++/*! \cidoxg_include_ci_compat */
++
++#ifndef __CI_COMPAT_PRIMITIVE_H__
++#define __CI_COMPAT_PRIMITIVE_H__
++
++
++/**********************************************************************
++ * Primitive types.
++ */
++
++typedef unsigned char ci_uint8;
++typedef char ci_int8;
++
++typedef unsigned short ci_uint16;
++typedef short ci_int16;
++
++typedef unsigned int ci_uint32;
++typedef int ci_int32;
++
++/* 64-bit support is platform dependent. */
++
++
++/**********************************************************************
++ * Other fancy types.
++ */
++
++typedef ci_uint8 ci_octet;
++
++typedef enum {
++ CI_FALSE = 0,
++ CI_TRUE
++} ci_boolean_t;
++
++
++/**********************************************************************
++ * Some nice types you'd always assumed were standards.
++ * (Really, they are SYSV "standards".)
++ */
++
++#ifdef _WIN32
++typedef unsigned long ulong;
++typedef unsigned int uint;
++typedef char* caddr_t;
++#elif defined(__linux__) && defined(__KERNEL__)
++#include <linux/types.h>
++#elif defined(__linux__)
++#include <sys/types.h>
++#endif
++
++
++#endif /* __CI_COMPAT_PRIMITIVE_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/sysdep.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/sysdep.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,166 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*! \cidoxg_include_ci_compat */
++
++#ifndef __CI_COMPAT_SYSDEP_H__
++#define __CI_COMPAT_SYSDEP_H__
++
++
++/**********************************************************************
++ * Platform definition fixups.
++ */
++
++#if defined(__ci_ul_driver__) && !defined(__ci_driver__)
++# define __ci_driver__
++#endif
++
++#if defined(__ci_driver__) && !defined(__ci_ul_driver__) && \
++ !defined(__KERNEL__)
++# define __KERNEL__
++#endif
++
++
++/**********************************************************************
++ * Sanity checks (no cheating!)
++ */
++
++#if defined(__KERNEL__) && !defined(__ci_driver__)
++# error Insane.
++#endif
++
++#if defined(__KERNEL__) && defined(__ci_ul_driver__)
++# error Madness.
++#endif
++
++#if defined(__unix__) && defined(_WIN32)
++# error Strange.
++#endif
++
++#if defined(__GNUC__) && defined(_MSC_VER)
++# error Crazy.
++#endif
++
++
++/**********************************************************************
++ * Compiler and processor dependencies.
++ */
++
++#if defined(__GNUC__)
++
++# include <ci/compat/gcc.h>
++
++# if defined(__i386__)
++# include <ci/compat/x86.h>
++# include <ci/compat/gcc_x86.h>
++# elif defined(__x86_64__)
++# include <ci/compat/x86_64.h>
++# include <ci/compat/gcc_x86.h>
++# elif defined(__PPC__)
++# include <ci/compat/ppc.h>
++# include <ci/compat/gcc_ppc.h>
++# elif defined(__ia64__)
++# include <ci/compat/ia64.h>
++# include <ci/compat/gcc_ia64.h>
++# else
++# error Unknown processor - GNU C
++# endif
++
++#elif defined(_MSC_VER)
++
++# include <ci/compat/msvc.h>
++
++# if defined(__i386__)
++# include <ci/compat/x86.h>
++# include <ci/compat/msvc_x86.h>
++# elif defined(__x86_64__)
++# include <ci/compat/x86_64.h>
++# include <ci/compat/msvc_x86_64.h>
++# else
++# error Unknown processor MSC
++# endif
++
++#elif defined(__PGI)
++
++# include <ci/compat/x86.h>
++# include <ci/compat/pg_x86.h>
++
++#elif defined(__INTEL_COMPILER)
++
++/* Intel compilers v7 claim to be very gcc compatible. */
++# if __INTEL_COMPILER >= 700
++# include <ci/compat/gcc.h>
++# include <ci/compat/x86.h>
++# include <ci/compat/gcc_x86.h>
++# else
++# error Old Intel compiler not supported. Yet.
++# endif
++
++#else
++# error Unknown compiler.
++#endif
++
++
++/**********************************************************************
++ * Misc stuff (that probably shouldn't be here).
++ */
++
++#ifdef __sun
++# ifdef __KERNEL__
++# define _KERNEL
++# define _SYSCALL32
++# ifdef _LP64
++# define _SYSCALL32_IMPL
++# endif
++# else
++# define _REENTRANT
++# endif
++#endif
++
++
++/**********************************************************************
++ * Defaults for anything left undefined.
++ */
++
++#ifndef CI_LIKELY
++# define CI_LIKELY(t) (t)
++# define CI_UNLIKELY(t) (t)
++#endif
++
++#ifndef ci_restrict
++# define ci_restrict
++#endif
++
++#ifndef ci_inline
++# define ci_inline static inline
++#endif
++
++#ifndef ci_noinline
++# define ci_noinline static
++#endif
++
++#endif /* __CI_COMPAT_SYSDEP_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/utils.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/utils.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/utils.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/utils.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,269 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr
++ * \brief Handy utility macros.
++ * \date 2003/01/17
++ */
++
++/*! \cidoxg_include_ci_compat */
++
++#ifndef __CI_COMPAT_UTILS_H__
++#define __CI_COMPAT_UTILS_H__
++
++
++/**********************************************************************
++ * Alignment -- [align] must be a power of 2.
++ **********************************************************************/
++
++ /*! Align forward onto next boundary. */
++
++#define CI_ALIGN_FWD(p, align) (((p)+(align)-1u) & ~((align)-1u))
++
++
++ /*! Align back onto prev boundary. */
++
++#define CI_ALIGN_BACK(p, align) ((p) & ~((align)-1u))
++
++
++ /*! How far to next boundary? */
++
++#define CI_ALIGN_NEEDED(p, align, signed_t) (-(signed_t)(p) & ((align)-1u))
++
++
++ /*! How far beyond prev boundary? */
++
++#define CI_OFFSET(p, align) ((p) & ((align)-1u))
++
++
++ /*! Does object fit in gap before next boundary? */
++
++#define CI_FITS(p, size, align, signed_t) \
++ (CI_ALIGN_NEEDED((p) + 1, (align), signed_t) + 1 >= (size))
++
++
++ /*! Align forward onto next boundary. */
++
++#define CI_PTR_ALIGN_FWD(p, align) \
++ ((char*) CI_ALIGN_FWD(((ci_ptr_arith_t)(p)), ((ci_ptr_arith_t)(align))))
++
++ /*! Align back onto prev boundary. */
++
++#define CI_PTR_ALIGN_BACK(p, align) \
++ ((char*) CI_ALIGN_BACK(((ci_ptr_arith_t)(p)), ((ci_ptr_arith_t)(align))))
++
++ /*! How far to next boundary? */
++
++#define CI_PTR_ALIGN_NEEDED(p, align) \
++ CI_ALIGN_NEEDED(((ci_ptr_arith_t)(p)), ((ci_ptr_arith_t)(align)), \
++ ci_ptr_arith_t)
++
++ /*! How far to next boundary? NZ = not zero i.e. give align if on boundary */
++
++#define CI_PTR_ALIGN_NEEDED_NZ(p, align) \
++ ((align) - (((char*)p) - \
++ ((char*) CI_ALIGN_BACK(((ci_ptr_arith_t)(p)), ((ci_ptr_arith_t)(align))))))
++
++ /*! How far beyond prev boundary? */
++
++#define CI_PTR_OFFSET(p, align) \
++ CI_OFFSET(((ci_ptr_arith_t)(p)), ((ci_ptr_arith_t)(align)))
++
++
++ /* Same as CI_ALIGN_FWD and CI_ALIGN_BACK. */
++
++#define CI_ROUND_UP(i, align) (((i)+(align)-1u) & ~((align)-1u))
++
++#define CI_ROUND_DOWN(i, align) ((i) & ~((align)-1u))
++
++
++/**********************************************************************
++ * Byte-order
++ **********************************************************************/
++
++/* These are not flags. They are enumeration values for use with
++ * CI_MY_BYTE_ORDER. */
++#define CI_BIG_ENDIAN 1
++#define CI_LITTLE_ENDIAN 0
++
++/*
++** Note that these byte-swapping primitives may leave junk in bits above
++** the range they operate on.
++**
++** The CI_BSWAP_nn() routines require that bits above [nn] are zero. Use
++** CI_BSWAPM_nn(x) if this cannot be guaranteed.
++*/
++
++/* ?? May be able to improve on some of these with inline assembler on some
++** platforms.
++*/
++
++#define CI_BSWAP_16(v) ((((v) & 0xff) << 8) | ((v) >> 8))
++#define CI_BSWAPM_16(v) ((((v) & 0xff) << 8) | (((v) & 0xff00) >> 8))
++
++#define CI_BSWAP_32(v) (((v) >> 24) | \
++ (((v) & 0x00ff0000) >> 8) | \
++ (((v) & 0x0000ff00) << 8) | \
++ ((v) << 24))
++#define CI_BSWAPM_32(v) ((((v) & 0xff000000) >> 24) | \
++ (((v) & 0x00ff0000) >> 8) | \
++ (((v) & 0x0000ff00) << 8) | \
++ ((v) << 24))
++
++#define CI_BSWAP_64(v) (((v) >> 56) | \
++ (((v) & 0x00ff000000000000) >> 40) | \
++ (((v) & 0x0000ff0000000000) >> 24) | \
++ (((v) & 0x000000ff00000000) >> 8) | \
++ (((v) & 0x00000000ff000000) << 8) | \
++ (((v) & 0x0000000000ff0000) << 24) | \
++ (((v) & 0x000000000000ff00) << 40) | \
++ ((v) << 56))
++
++# define CI_BSWAPPED_16_IF(c,v) ((c) ? CI_BSWAP_16(v) : (v))
++# define CI_BSWAPPED_32_IF(c,v) ((c) ? CI_BSWAP_32(v) : (v))
++# define CI_BSWAPPED_64_IF(c,v) ((c) ? CI_BSWAP_64(v) : (v))
++# define CI_BSWAP_16_IF(c,v) do{ if((c)) (v) = CI_BSWAP_16(v); }while(0)
++# define CI_BSWAP_32_IF(c,v) do{ if((c)) (v) = CI_BSWAP_32(v); }while(0)
++# define CI_BSWAP_64_IF(c,v) do{ if((c)) (v) = CI_BSWAP_64(v); }while(0)
++
++#if (CI_MY_BYTE_ORDER == CI_LITTLE_ENDIAN)
++# define CI_BSWAP_LE16(v) (v)
++# define CI_BSWAP_LE32(v) (v)
++# define CI_BSWAP_LE64(v) (v)
++# define CI_BSWAP_BE16(v) CI_BSWAP_16(v)
++# define CI_BSWAP_BE32(v) CI_BSWAP_32(v)
++# define CI_BSWAP_BE64(v) CI_BSWAP_64(v)
++# define CI_BSWAPM_LE16(v) (v)
++# define CI_BSWAPM_LE32(v) (v)
++# define CI_BSWAPM_LE64(v) (v)
++# define CI_BSWAPM_BE16(v) CI_BSWAPM_16(v)
++# define CI_BSWAPM_BE32(v) CI_BSWAPM_32(v)
++#elif (CI_MY_BYTE_ORDER == CI_BIG_ENDIAN)
++# define CI_BSWAP_BE16(v) (v)
++# define CI_BSWAP_BE32(v) (v)
++# define CI_BSWAP_BE64(v) (v)
++# define CI_BSWAP_LE16(v) CI_BSWAP_16(v)
++# define CI_BSWAP_LE32(v) CI_BSWAP_32(v)
++# define CI_BSWAP_LE64(v) CI_BSWAP_64(v)
++# define CI_BSWAPM_BE16(v) (v)
++# define CI_BSWAPM_BE32(v) (v)
++# define CI_BSWAPM_BE64(v) (v)
++# define CI_BSWAPM_LE16(v) CI_BSWAPM_16(v)
++# define CI_BSWAPM_LE32(v) CI_BSWAPM_32(v)
++#else
++# error Bad endian.
++#endif
++
++
++/**********************************************************************
++ * Get pointer to struct from pointer to member
++ **********************************************************************/
++
++#define CI_MEMBER_OFFSET(c_type, mbr_name) \
++ ((ci_uint32) (ci_uintptr_t)(&((c_type*)0)->mbr_name))
++
++#define CI_MEMBER_SIZE(c_type, mbr_name) \
++ sizeof(((c_type*)0)->mbr_name)
++
++#define __CI_CONTAINER(c_type, mbr_name, p_mbr) \
++ ( (c_type*) ((char*)(p_mbr) - CI_MEMBER_OFFSET(c_type, mbr_name)) )
++
++#ifndef CI_CONTAINER
++# define CI_CONTAINER(t,m,p) __CI_CONTAINER(t,m,p)
++#endif
++
++
++/**********************************************************************
++ * Structure member initialiser.
++ **********************************************************************/
++
++#ifndef CI_STRUCT_MBR
++# define CI_STRUCT_MBR(name, val) .name = val
++#endif
++
++
++/**********************************************************************
++ * min / max
++ **********************************************************************/
++
++#define CI_MIN(x,y) (((x) < (y)) ? (x) : (y))
++#define CI_MAX(x,y) (((x) > (y)) ? (x) : (y))
++
++/**********************************************************************
++ * abs
++ **********************************************************************/
++
++#define CI_ABS(x) (((x) < 0) ? -(x) : (x))
++
++/**********************************************************************
++ * Conditional debugging
++ **********************************************************************/
++
++#ifdef NDEBUG
++# define CI_DEBUG(x)
++# define CI_NDEBUG(x) x
++# define CI_IF_DEBUG(y,n) (n)
++# define CI_DEBUG_ARG(x)
++#else
++# define CI_DEBUG(x) x
++# define CI_NDEBUG(x)
++# define CI_IF_DEBUG(y,n) (y)
++# define CI_DEBUG_ARG(x) ,x
++#endif
++
++#ifdef __KERNEL__
++#define CI_KERNEL_ARG(x) ,x
++#else
++#define CI_KERNEL_ARG(x)
++#endif
++
++#ifdef _WIN32
++# define CI_KERNEL_ARG_WIN(x) CI_KERNEL_ARG(x)
++# define CI_ARG_WIN(x) ,x
++#else
++# define CI_KERNEL_ARG_WIN(x)
++# define CI_ARG_WIN(x)
++#endif
++
++#ifdef __unix__
++# define CI_KERNEL_ARG_UNIX(x) CI_KERNEL_ARG(x)
++# define CI_ARG_UNIX(x) ,x
++#else
++# define CI_KERNEL_ARG_UNIX(x)
++# define CI_ARG_UNIX(x)
++#endif
++
++#ifdef __linux__
++# define CI_KERNEL_ARG_LINUX(x) CI_KERNEL_ARG(x)
++# define CI_ARG_LINUX(x) ,x
++#else
++# define CI_KERNEL_ARG_LINUX(x)
++# define CI_ARG_LINUX(x)
++#endif
++
++
++#endif /* __CI_COMPAT_UTILS_H__ */
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/x86_64.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/x86_64.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/x86_64.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/x86_64.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,54 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr
++ * \brief Arch stuff for AMD x86_64.
++ * \date 2004/08/17
++ */
++
++/*! \cidoxg_include_ci_compat */
++#ifndef __CI_COMPAT_X86_64_H__
++#define __CI_COMPAT_X86_64_H__
++
++
++#define CI_MY_BYTE_ORDER CI_LITTLE_ENDIAN
++
++#define CI_WORD_SIZE 8
++#define CI_PTR_SIZE 8
++
++#define CI_PAGE_SIZE 4096
++#define CI_PAGE_SHIFT 12
++#define CI_PAGE_MASK (~(CI_PAGE_SIZE - 1))
++
++#define CI_CPU_HAS_SSE 1 /* SSE extensions supported */
++
++/* SSE2 disabled while investigating BUG1060 */
++#define CI_CPU_HAS_SSE2 0 /* SSE2 extensions supported */
++#define CI_CPU_OOS 0 /* CPU does out of order stores */
++
++
++#endif /* __CI_COMPAT_X86_64_H__ */
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/x86.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/x86.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat/x86.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat/x86.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,48 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*! \cidoxg_include_ci_compat */
++
++#ifndef __CI_COMPAT_X86_H__
++#define __CI_COMPAT_X86_H__
++
++
++#define CI_MY_BYTE_ORDER CI_LITTLE_ENDIAN
++
++#define CI_WORD_SIZE 4
++#define CI_PTR_SIZE 4
++
++#define CI_PAGE_SIZE 4096
++#define CI_PAGE_SHIFT 12
++#define CI_PAGE_MASK (~(CI_PAGE_SIZE - 1))
++
++#define CI_CPU_HAS_SSE 1 /* SSE extensions supported */
++#define CI_CPU_HAS_SSE2 0 /* SSE2 extensions supported */
++#define CI_CPU_OOS 0 /* CPU does out of order stores */
++
++
++#endif /* __CI_COMPAT_X86_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/compat.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/compat.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,53 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr
++ * \brief Compatability layer. Provides definitions of fundamental
++ * types and definitions that are used throughout CI source
++ * code. It does not introduce any link time dependencies,
++ * or include any unnecessary system headers.
++ */
++/*! \cidoxg_include_ci */
++
++#ifndef __CI_COMPAT_H__
++#define __CI_COMPAT_H__
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#include <ci/compat/primitive.h>
++#include <ci/compat/sysdep.h>
++#include <ci/compat/utils.h>
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* __CI_COMPAT_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/driver/resource/efx_vi.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/driver/resource/efx_vi.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/driver/resource/efx_vi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/driver/resource/efx_vi.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,276 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains public EFX VI API to Solarflare resource manager.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_RESOURCE_EFX_VI_H__
++#define __CI_DRIVER_RESOURCE_EFX_VI_H__
++
++/* Default size of event queue in the efx_vi resource. Copied from
++ * CI_CFG_NETIF_EVENTQ_SIZE */
++#define EFX_VI_EVENTQ_SIZE_DEFAULT 1024
++
++extern int efx_vi_eventq_size;
++
++/**************************************************************************
++ * efx_vi_state types, allocation and free
++ **************************************************************************/
++
++/*! Handle for refering to a efx_vi */
++struct efx_vi_state;
++
++/*!
++ * Allocate an efx_vi, including event queue and pt_endpoint
++ *
++ * \param vih_out Pointer to a handle that is set on success
++ * \param nic_index Index of NIC to apply this resource to
++ * \return Zero on success (and vih_out set), non-zero on failure.
++ */
++extern int
++efx_vi_alloc(struct efx_vi_state **vih_out, int nic_index);
++
++/*!
++ * Free a previously allocated efx_vi
++ *
++ * \param vih The handle of the efx_vi to free
++ */
++extern void
++efx_vi_free(struct efx_vi_state *vih);
++
++/*!
++ * Reset a previously allocated efx_vi
++ *
++ * \param vih The handle of the efx_vi to reset
++ */
++extern void
++efx_vi_reset(struct efx_vi_state *vih);
++
++/**************************************************************************
++ * efx_vi_eventq types and functions
++ **************************************************************************/
++
++/*!
++ * Register a function to receive callbacks when event queue timeouts
++ * or wakeups occur. Only one function per efx_vi can be registered
++ * at once.
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param callback The function to callback
++ * \param context An argument to pass to the callback function
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_eventq_register_callback(struct efx_vi_state *vih,
++ void (*callback)(void *context, int is_timeout),
++ void *context);
++
++/*!
++ * Remove the current eventq timeout or wakeup callback function
++ *
++ * \param vih The handle to identify the efx_vi
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_eventq_kill_callback(struct efx_vi_state *vih);
++
++/**************************************************************************
++ * efx_vi_dma_map types and functions
++ **************************************************************************/
++
++/*!
++ * Handle for refering to a efx_vi
++ */
++struct efx_vi_dma_map_state;
++
++/*!
++ * Map a list of buffer pages so they are registered with the hardware
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param addrs An array of page pointers to map
++ * \param n_addrs Length of the page pointer array. Must be a power of two.
++ * \param dmh_out Set on success to a handle used to refer to this mapping
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_dma_map_pages(struct efx_vi_state *vih, struct page **pages,
++ int n_pages, struct efx_vi_dma_map_state **dmh_out);
++extern int
++efx_vi_dma_map_addrs(struct efx_vi_state *vih,
++ unsigned long long *dev_bus_addrs, int n_pages,
++ struct efx_vi_dma_map_state **dmh_out);
++
++/*!
++ * Unmap a previously mapped set of pages so they are no longer registered
++ * with the hardware.
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param dmh The handle to identify the dma mapping
++ */
++extern void
++efx_vi_dma_unmap_pages(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh);
++extern void
++efx_vi_dma_unmap_addrs(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh);
++
++/*!
++ * Retrieve the buffer address of the mapping
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param dmh The handle to identify the buffer mapping
++ * \return The buffer address on success, or zero on failure
++ */
++extern unsigned
++efx_vi_dma_get_map_addr(struct efx_vi_state *vih,
++ struct efx_vi_dma_map_state *dmh);
++
++/**************************************************************************
++ * efx_vi filter functions
++ **************************************************************************/
++
++#define EFX_VI_STATIC_FILTERS 32
++
++/*! Handle to refer to a filter instance */
++struct filter_resource_t;
++
++/*!
++ * Allocate and add a filter
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param protocol The protocol of the new filter: UDP or TCP
++ * \param ip_addr_be32 The local ip address of the filter
++ * \param port_le16 The local port of the filter
++ * \param fh_out Set on success to be a handle to refer to this filter
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_filter(struct efx_vi_state *vih, int protocol, unsigned ip_addr_be32,
++ int port_le16, struct filter_resource_t **fh_out);
++
++/*!
++ * Remove a filter and free resources associated with it
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param fh The handle to identify the filter
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_filter_stop(struct efx_vi_state *vih, struct filter_resource_t *fh);
++
++/**************************************************************************
++ * efx_vi hw resources types and functions
++ **************************************************************************/
++
++/*! Constants for the type field in efx_vi_hw_resource */
++#define EFX_VI_HW_RESOURCE_TXDMAQ 0x0 /* PFN of TX DMA Q */
++#define EFX_VI_HW_RESOURCE_RXDMAQ 0x1 /* PFN of RX DMA Q */
++#define EFX_VI_HW_RESOURCE_TXBELL 0x2 /* PFN of TX Doorbell (EF1) */
++#define EFX_VI_HW_RESOURCE_RXBELL 0x3 /* PFN of RX Doorbell (EF1) */
++#define EFX_VI_HW_RESOURCE_EVQTIMER 0x4 /* Address of event q timer */
++
++/* Address of event q pointer (EF1) */
++#define EFX_VI_HW_RESOURCE_EVQPTR 0x5
++/* Address of register pointer (Falcon A) */
++#define EFX_VI_HW_RESOURCE_EVQRPTR 0x6
++/* Offset of register pointer (Falcon B) */
++#define EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET 0x7
++/* Address of mem KVA */
++#define EFX_VI_HW_RESOURCE_EVQMEMKVA 0x8
++/* PFN of doorbell page (Falcon) */
++#define EFX_VI_HW_RESOURCE_BELLPAGE 0x9
++
++/*! How large an array to allocate for the get_() functions - smaller
++ than the total number of constants as some are mutually exclusive */
++#define EFX_VI_HW_RESOURCE_MAXSIZE 0x7
++
++/*! Constants for the mem_type field in efx_vi_hw_resource */
++#define EFX_VI_HW_RESOURCE_IOBUFFER 0 /* Host memory */
++#define EFX_VI_HW_RESOURCE_PERIPHERAL 1 /* Card memory/registers */
++
++/*!
++ * Data structure providing information on a hardware resource mapping
++ */
++struct efx_vi_hw_resource {
++ u8 type; /*!< What this resource represents */
++ u8 mem_type; /*!< What type of memory is it in, eg,
++ * host or iomem */
++ u8 more_to_follow; /*!< Is this part of a multi-region resource */
++ u32 length; /*!< Length of the resource in bytes */
++ unsigned long address; /*!< Address of this resource */
++};
++
++/*!
++ * Metadata concerning the list of hardware resource mappings
++ */
++struct efx_vi_hw_resource_metadata {
++ int version;
++ int evq_order;
++ int evq_offs;
++ int evq_capacity;
++ int instance;
++ unsigned rx_capacity;
++ unsigned tx_capacity;
++ int nic_arch;
++ int nic_revision;
++ char nic_variant;
++};
++
++/*!
++ * Obtain a list of hardware resource mappings, using virtual addresses
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param mdata Pointer to a structure to receive the metadata
++ * \param hw_res_array An array to receive the list of hardware resources
++ * \param length The length of hw_res_array. Updated on success to contain
++ * the number of entries in the supplied array that were used.
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_hw_resource_get_virt(struct efx_vi_state *vih,
++ struct efx_vi_hw_resource_metadata *mdata,
++ struct efx_vi_hw_resource *hw_res_array,
++ int *length);
++
++/*!
++ * Obtain a list of hardware resource mappings, using physical addresses
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param mdata Pointer to a structure to receive the metadata
++ * \param hw_res_array An array to receive the list of hardware resources
++ * \param length The length of hw_res_array. Updated on success to contain
++ * the number of entries in the supplied array that were used.
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_hw_resource_get_phys(struct efx_vi_state *vih,
++ struct efx_vi_hw_resource_metadata *mdata,
++ struct efx_vi_hw_resource *hw_res_array,
++ int *length);
++
++#endif /* __CI_DRIVER_RESOURCE_EFX_VI_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/common.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/common.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/common.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,102 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides API of the efhw library which may be used both from
++ * the kernel and from the user-space code.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_COMMON_H__
++#define __CI_EFHW_COMMON_H__
++
++#include <ci/efhw/common_sysdep.h>
++
++enum efhw_arch {
++ EFHW_ARCH_FALCON,
++ EFHW_ARCH_SIENA,
++};
++
++typedef uint32_t efhw_buffer_addr_t;
++#define EFHW_BUFFER_ADDR_FMT "[ba:%"PRIx32"]"
++
++/*! Comment? */
++typedef union {
++ uint64_t u64;
++ struct {
++ uint32_t a;
++ uint32_t b;
++ } opaque;
++ struct {
++ uint32_t code;
++ uint32_t status;
++ } ev1002;
++} efhw_event_t;
++
++/* Flags for TX/RX queues */
++#define EFHW_VI_JUMBO_EN 0x01 /*! scatter RX over multiple desc */
++#define EFHW_VI_ISCSI_RX_HDIG_EN 0x02 /*! iscsi rx header digest */
++#define EFHW_VI_ISCSI_TX_HDIG_EN 0x04 /*! iscsi tx header digest */
++#define EFHW_VI_ISCSI_RX_DDIG_EN 0x08 /*! iscsi rx data digest */
++#define EFHW_VI_ISCSI_TX_DDIG_EN 0x10 /*! iscsi tx data digest */
++#define EFHW_VI_TX_PHYS_ADDR_EN 0x20 /*! TX physical address mode */
++#define EFHW_VI_RX_PHYS_ADDR_EN 0x40 /*! RX physical address mode */
++#define EFHW_VI_RM_WITH_INTERRUPT 0x80 /*! VI with an interrupt */
++#define EFHW_VI_TX_IP_CSUM_DIS 0x100 /*! enable ip checksum generation */
++#define EFHW_VI_TX_TCPUDP_CSUM_DIS 0x200 /*! enable tcp/udp checksum
++ generation */
++#define EFHW_VI_TX_TCPUDP_ONLY 0x400 /*! drop non-tcp/udp packets */
++
++/* Types of hardware filter */
++/* Each of these values implicitly selects scatter filters on B0 - or in
++ EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK if a non-scatter filter is required */
++#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD (0) /* dest host only */
++#define EFHW_IP_FILTER_TYPE_UDP_FULL (1) /* dest host and port */
++#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD (2) /* dest based filter */
++#define EFHW_IP_FILTER_TYPE_TCP_FULL (3) /* src filter */
++/* Same again, but with RSS (for B0 only) */
++#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD_RSS_B0 (4)
++#define EFHW_IP_FILTER_TYPE_UDP_FULL_RSS_B0 (5)
++#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD_RSS_B0 (6)
++#define EFHW_IP_FILTER_TYPE_TCP_FULL_RSS_B0 (7)
++
++#define EFHW_IP_FILTER_TYPE_FULL_MASK (0x1) /* Mask for full / wildcard */
++#define EFHW_IP_FILTER_TYPE_TCP_MASK (0x2) /* Mask for TCP type */
++#define EFHW_IP_FILTER_TYPE_RSS_B0_MASK (0x4) /* Mask for B0 RSS enable */
++#define EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK (0x8) /* Mask for B0 SCATTER dsbl */
++
++#define EFHW_IP_FILTER_TYPE_MASK (0xffff) /* Mask of types above */
++
++#define EFHW_IP_FILTER_BROADCAST (0x10000) /* driverlink filter
++ support */
++
++#endif /* __CI_EFHW_COMMON_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/common_sysdep.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/common_sysdep.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/common_sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/common_sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,67 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for
++ * userland-to-kernel interfaces.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_COMMON_LINUX_H__
++#define __CI_EFHW_COMMON_LINUX_H__
++
++#include <linux/types.h>
++#include <linux/version.h>
++
++/* Dirty hack, but Linux kernel does not provide DMA_ADDR_T_FMT */
++#if BITS_PER_LONG == 64 || defined(CONFIG_HIGHMEM64G)
++#define DMA_ADDR_T_FMT "%llx"
++#else
++#define DMA_ADDR_T_FMT "%x"
++#endif
++
++/* Linux kernel also does not provide PRIx32... Sigh. */
++#define PRIx32 "x"
++#define PRIx64 "llx"
++
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++enum {
++ false = 0,
++ true = 1
++};
++
++typedef _Bool bool;
++#endif /* LINUX_VERSION_CODE < 2.6.19 */
++
++#endif /* __CI_EFHW_COMMON_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/debug.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/debug.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/debug.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,84 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides debug-related API for efhw library using Linux kernel
++ * primitives.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_DEBUG_LINUX_H__
++#define __CI_EFHW_DEBUG_LINUX_H__
++
++#define EFHW_PRINTK_PREFIX "[sfc efhw] "
++
++#define EFHW_PRINTK(level, fmt, ...) \
++ printk(level EFHW_PRINTK_PREFIX fmt "\n", __VA_ARGS__)
++
++/* Following macros should be used with non-zero format parameters
++ * due to __VA_ARGS__ limitations. Use "%s" with __FUNCTION__ if you can't
++ * find better parameters. */
++#define EFHW_ERR(fmt, ...) EFHW_PRINTK(KERN_ERR, fmt, __VA_ARGS__)
++#define EFHW_WARN(fmt, ...) EFHW_PRINTK(KERN_WARNING, fmt, __VA_ARGS__)
++#define EFHW_NOTICE(fmt, ...) EFHW_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__)
++#if 0 && !defined(NDEBUG)
++#define EFHW_TRACE(fmt, ...) EFHW_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__)
++#else
++#define EFHW_TRACE(fmt, ...)
++#endif
++
++#ifndef NDEBUG
++#define EFHW_ASSERT(cond) BUG_ON((cond) == 0)
++#define EFHW_DO_DEBUG(expr) expr
++#else
++#define EFHW_ASSERT(cond)
++#define EFHW_DO_DEBUG(expr)
++#endif
++
++#define EFHW_TEST(expr) \
++ do { \
++ if (unlikely(!(expr))) \
++ BUG(); \
++ } while (0)
++
++/* Build time asserts. We paste the line number into the type name
++ * so that the macro can be used more than once per file even if the
++ * compiler objects to multiple identical typedefs. Collisions
++ * between use in different header files is still possible. */
++#ifndef EFHW_BUILD_ASSERT
++#define __EFHW_BUILD_ASSERT_NAME(_x) __EFHW_BUILD_ASSERT_ILOATHECPP(_x)
++#define __EFHW_BUILD_ASSERT_ILOATHECPP(_x) __EFHW_BUILD_ASSERT__ ##_x
++#define EFHW_BUILD_ASSERT(e) \
++ typedef char __EFHW_BUILD_ASSERT_NAME(__LINE__)[(e) ? 1 : -1]
++#endif
++
++#endif /* __CI_EFHW_DEBUG_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/efhw_config.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/efhw_config.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/efhw_config.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/efhw_config.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,43 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides some limits used in both kernel and userland code.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EFAB_CONFIG_H__
++#define __CI_EFHW_EFAB_CONFIG_H__
++
++#define EFHW_MAX_NR_DEVS 5 /* max number of efhw devices supported */
++
++#endif /* __CI_EFHW_EFAB_CONFIG_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/efhw_types.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/efhw_types.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/efhw_types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/efhw_types.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,342 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides struct efhw_nic and some related types.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EFAB_TYPES_H__
++#define __CI_EFHW_EFAB_TYPES_H__
++
++#include <ci/efhw/efhw_config.h>
++#include <ci/efhw/hardware_sysdep.h>
++#include <ci/efhw/iopage_types.h>
++#include <ci/efhw/sysdep.h>
++
++/*--------------------------------------------------------------------
++ *
++ * hardware limits used in the types
++ *
++ *--------------------------------------------------------------------*/
++
++#define EFHW_KEVENTQ_MAX 8
++
++/*--------------------------------------------------------------------
++ *
++ * forward type declarations
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_nic;
++
++/*--------------------------------------------------------------------
++ *
++ * Managed interface
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_buffer_table_allocation{
++ unsigned base;
++ unsigned order;
++};
++
++struct eventq_resource_hardware {
++ /*!iobuffer allocated for eventq - can be larger than eventq */
++ efhw_iopages_t iobuff;
++ unsigned iobuff_off;
++ struct efhw_buffer_table_allocation buf_tbl_alloc;
++ int capacity; /*!< capacity of event queue */
++};
++
++/*--------------------------------------------------------------------
++ *
++ * event queues and event driven callbacks
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_keventq {
++ volatile int lock;
++ caddr_t evq_base;
++ int32_t evq_ptr;
++ uint32_t evq_mask;
++ unsigned instance;
++ struct eventq_resource_hardware hw;
++ struct efhw_ev_handler *ev_handlers;
++};
++
++/**********************************************************************
++ * Portable HW interface. ***************************************
++ **********************************************************************/
++
++/*--------------------------------------------------------------------
++ *
++ * EtherFabric Functional units - configuration and control
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_func_ops {
++
++ /*-------------- Initialisation ------------ */
++
++ /*! close down all hardware functional units - leaves NIC in a safe
++ state for driver unload */
++ void (*close_hardware) (struct efhw_nic *nic);
++
++ /*! initialise all hardware functional units */
++ int (*init_hardware) (struct efhw_nic *nic,
++ struct efhw_ev_handler *,
++ const uint8_t *mac_addr);
++
++ /*-------------- Interrupt support ------------ */
++
++ /*! Main interrupt routine
++ ** This function returns,
++ ** - zero, if the IRQ was not generated by EF1
++ ** - non-zero, if EF1 was the source of the IRQ
++ **
++ **
++ ** opaque is an OS provided pointer for use by the OS callbacks
++ ** e.g in Windows used to indicate DPC scheduled
++ */
++ int (*interrupt) (struct efhw_nic *nic);
++
++ /*! Enable given interrupt mask for the given IRQ unit */
++ void (*interrupt_enable) (struct efhw_nic *nic, uint idx);
++
++ /*! Disable given interrupt mask for the given IRQ unit */
++ void (*interrupt_disable) (struct efhw_nic *nic, uint idx);
++
++ /*! Set interrupt moderation strategy for the given IRQ unit
++ ** val is in usec
++ */
++ void (*set_interrupt_moderation)(struct efhw_nic *nic,
++ uint idx, uint val);
++
++ /*-------------- Event support ------------ */
++
++ /*! Enable the given event queue
++ depending on the underlying implementation (EF1 or Falcon) then
++ either a q_base_addr in host memory, or a buffer base id should
++ be proivded
++ */
++ void (*event_queue_enable) (struct efhw_nic *nic,
++ uint evq, /* evnt queue index */
++ uint evq_size, /* units of #entries */
++ dma_addr_t q_base_addr, uint buf_base_id);
++
++ /*! Disable the given event queue (and any associated timer) */
++ void (*event_queue_disable) (struct efhw_nic *nic, uint evq,
++ int timer_only);
++
++ /*! request wakeup from the NIC on a given event Q */
++ void (*wakeup_request) (struct efhw_nic *nic, dma_addr_t q_base_addr,
++ int next_i, int evq);
++
++ /*! Push a SW event on a given eventQ */
++ void (*sw_event) (struct efhw_nic *nic, int data, int evq);
++
++ /*-------------- Filter support ------------ */
++
++ /*! Setup a given filter - The software can request a filter_i,
++ * but some EtherFabric implementations will override with
++ * a more suitable index
++ */
++ int (*ipfilter_set) (struct efhw_nic *nic, int type,
++ int *filter_i, int dmaq,
++ unsigned saddr_be32, unsigned sport_be16,
++ unsigned daddr_be32, unsigned dport_be16);
++
++ /*! Attach a given filter to a DMAQ */
++ void (*ipfilter_attach) (struct efhw_nic *nic, int filter_idx,
++ int dmaq_idx);
++
++ /*! Detach a filter from its DMAQ */
++ void (*ipfilter_detach) (struct efhw_nic *nic, int filter_idx);
++
++ /*! Clear down a given filter */
++ void (*ipfilter_clear) (struct efhw_nic *nic, int filter_idx);
++
++ /*-------------- DMA support ------------ */
++
++ /*! Initialise NIC state for a given TX DMAQ */
++ void (*dmaq_tx_q_init) (struct efhw_nic *nic,
++ uint dmaq, uint evq, uint owner, uint tag,
++ uint dmaq_size, uint buf_idx, uint flags);
++
++ /*! Initialise NIC state for a given RX DMAQ */
++ void (*dmaq_rx_q_init) (struct efhw_nic *nic,
++ uint dmaq, uint evq, uint owner, uint tag,
++ uint dmaq_size, uint buf_idx, uint flags);
++
++ /*! Disable a given TX DMAQ */
++ void (*dmaq_tx_q_disable) (struct efhw_nic *nic, uint dmaq);
++
++ /*! Disable a given RX DMAQ */
++ void (*dmaq_rx_q_disable) (struct efhw_nic *nic, uint dmaq);
++
++ /*! Flush a given TX DMA channel */
++ int (*flush_tx_dma_channel) (struct efhw_nic *nic, uint dmaq);
++
++ /*! Flush a given RX DMA channel */
++ int (*flush_rx_dma_channel) (struct efhw_nic *nic, uint dmaq);
++
++ /*-------------- Buffer table Support ------------ */
++
++ /*! Initialise a buffer table page */
++ void (*buffer_table_set) (struct efhw_nic *nic,
++ dma_addr_t dma_addr,
++ uint bufsz, uint region,
++ int own_id, int buffer_id);
++
++ /*! Initialise a block of buffer table pages */
++ void (*buffer_table_set_n) (struct efhw_nic *nic, int buffer_id,
++ dma_addr_t dma_addr,
++ uint bufsz, uint region,
++ int n_pages, int own_id);
++
++ /*! Clear a block of buffer table pages */
++ void (*buffer_table_clear) (struct efhw_nic *nic, int buffer_id,
++ int num);
++
++ /*! Commit a buffer table update */
++ void (*buffer_table_commit) (struct efhw_nic *nic);
++
++};
++
++
++/*----------------------------------------------------------------------------
++ *
++ * NIC type
++ *
++ *---------------------------------------------------------------------------*/
++
++struct efhw_device_type {
++ int arch; /* enum efhw_arch */
++ char variant; /* 'A', 'B', ... */
++ int revision; /* 0, 1, ... */
++};
++
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric NIC instance - nic.c for HW independent functions
++ *
++ *---------------------------------------------------------------------------*/
++
++/*! */
++struct efhw_nic {
++ /*! zero base index in efrm_nic_table.nic array */
++ volatile int index;
++ int ifindex; /*!< OS level nic index */
++#ifdef HAS_NET_NAMESPACE
++ struct net *nd_net;
++#endif
++
++ struct efhw_device_type devtype;
++
++ /*! Options that can be set by user. */
++ unsigned options;
++# define NIC_OPT_EFTEST 0x1 /* owner is an eftest app */
++
++# define NIC_OPT_DEFAULT 0
++
++ /*! Internal flags that indicate hardware properties at runtime. */
++ unsigned flags;
++# define NIC_FLAG_NO_INTERRUPT 0x01 /* to be set at init time only */
++# define NIC_FLAG_TRY_MSI 0x02
++# define NIC_FLAG_MSI 0x04
++# define NIC_FLAG_OS_IRQ_EN 0x08
++# define NIC_FLAG_10G 0x10
++
++ unsigned mtu; /*!< MAC MTU (includes MAC hdr) */
++
++ /* hardware resources */
++
++ /*! I/O address of the start of the bar */
++ efhw_ioaddr_t bar_ioaddr;
++
++ /*! Bar number of control aperture. */
++ unsigned ctr_ap_bar;
++ /*! Length of control aperture in bytes. */
++ unsigned ctr_ap_bytes;
++
++ uint8_t mac_addr[ETH_ALEN]; /*!< mac address */
++
++ /*! EtherFabric Functional Units -- functions */
++ const struct efhw_func_ops *efhw_func;
++
++ /* Value read from FPGA version register. Zero for asic. */
++ unsigned fpga_version;
++
++ /*! This lock protects a number of misc NIC resources. It should
++ * only be used for things that can be at the bottom of the lock
++ * order. ie. You mustn't attempt to grab any other lock while
++ * holding this one.
++ */
++ spinlock_t *reg_lock;
++ spinlock_t the_reg_lock;
++
++ int buf_commit_outstanding; /*!< outstanding buffer commits */
++
++ /*! interrupt callbacks (hard-irq) */
++ void (*irq_handler) (struct efhw_nic *, int unit);
++
++ /*! event queues per driver */
++ struct efhw_keventq evq[EFHW_KEVENTQ_MAX];
++
++/* for marking when we are not using an IRQ unit
++ - 0 is a valid offset to an IRQ unit on EF1! */
++#define EFHW_IRQ_UNIT_UNUSED 0xffff
++ /*! interrupt unit in use */
++ unsigned int irq_unit[EFHW_KEVENTQ_MAX];
++ efhw_iopage_t irq_iobuff; /*!< Falcon SYSERR interrupt */
++
++ /* The new driverlink infrastructure. */
++ struct efx_dl_device *net_driver_dev;
++ struct efx_dlfilt_cb_s *dlfilter_cb;
++
++ /*! Bit masks of the sizes of event queues and dma queues supported
++ * by the nic. */
++ unsigned evq_sizes;
++ unsigned rxq_sizes;
++ unsigned txq_sizes;
++
++ /* Size of filter table (including odd and even banks). */
++ unsigned filter_tbl_size;
++};
++
++
++#define EFHW_KVA(nic) ((nic)->bar_ioaddr)
++
++
++#endif /* __CI_EFHW_EFHW_TYPES_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/hardware_sysdep.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/hardware_sysdep.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/hardware_sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/hardware_sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,84 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for header files
++ * with hardware-related definitions (in ci/driver/efab/hardware*).
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_HARDWARE_LINUX_H__
++#define __CI_EFHW_HARDWARE_LINUX_H__
++
++#include <asm/io.h>
++
++#ifdef __LITTLE_ENDIAN
++#define EFHW_IS_LITTLE_ENDIAN
++#elif __BIG_ENDIAN
++#define EFHW_IS_BIG_ENDIAN
++#else
++#error Unknown endianness
++#endif
++
++#ifndef mmiowb
++ #if defined(__i386__) || defined(__x86_64__)
++ #define mmiowb()
++ #elif defined(__ia64__)
++ #ifndef ia64_mfa
++ #define ia64_mfa() asm volatile ("mf.a" ::: "memory")
++ #endif
++ #define mmiowb ia64_mfa
++ #else
++ #error "Need definition for mmiowb()"
++ #endif
++#endif
++
++typedef char *efhw_ioaddr_t;
++
++#ifndef readq
++static inline uint64_t __readq(void __iomem *addr)
++{
++ return *(volatile uint64_t *)addr;
++}
++#define readq(x) __readq(x)
++#endif
++
++#ifndef writeq
++static inline void __writeq(uint64_t v, void __iomem *addr)
++{
++ *(volatile uint64_t *)addr = v;
++}
++#define writeq(val, addr) __writeq((val), (addr))
++#endif
++
++#endif /* __CI_EFHW_HARDWARE_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/iopage_types.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/iopage_types.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/iopage_types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/iopage_types.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,188 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides efhw_page_t and efhw_iopage_t for Linux kernel.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_IOPAGE_LINUX_H__
++#define __CI_EFHW_IOPAGE_LINUX_H__
++
++#include <linux/gfp.h>
++#include <linux/hardirq.h>
++#include <ci/efhw/debug.h>
++
++/*--------------------------------------------------------------------
++ *
++ * efhw_page_t: A single page of memory. Directly mapped in the driver,
++ * and can be mapped to userlevel.
++ *
++ *--------------------------------------------------------------------*/
++
++typedef struct {
++ unsigned long kva;
++} efhw_page_t;
++
++static inline int efhw_page_alloc(efhw_page_t *p)
++{
++ p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
++ return p->kva ? 0 : -ENOMEM;
++}
++
++static inline int efhw_page_alloc_zeroed(efhw_page_t *p)
++{
++ p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
++ return p->kva ? 0 : -ENOMEM;
++}
++
++static inline void efhw_page_free(efhw_page_t *p)
++{
++ free_page(p->kva);
++ EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
++}
++
++static inline char *efhw_page_ptr(efhw_page_t *p)
++{
++ return (char *)p->kva;
++}
++
++static inline unsigned efhw_page_pfn(efhw_page_t *p)
++{
++ return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
++}
++
++static inline void efhw_page_mark_invalid(efhw_page_t *p)
++{
++ p->kva = 0;
++}
++
++static inline int efhw_page_is_valid(efhw_page_t *p)
++{
++ return p->kva != 0;
++}
++
++static inline void efhw_page_init_from_va(efhw_page_t *p, void *va)
++{
++ p->kva = (unsigned long)va;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * efhw_iopage_t: A single page of memory. Directly mapped in the driver,
++ * and can be mapped to userlevel. Can also be accessed by the NIC.
++ *
++ *--------------------------------------------------------------------*/
++
++typedef struct {
++ efhw_page_t p;
++ dma_addr_t dma_addr;
++} efhw_iopage_t;
++
++static inline dma_addr_t efhw_iopage_dma_addr(efhw_iopage_t *p)
++{
++ return p->dma_addr;
++}
++
++#define efhw_iopage_ptr(iop) efhw_page_ptr(&(iop)->p)
++#define efhw_iopage_pfn(iop) efhw_page_pfn(&(iop)->p)
++#define efhw_iopage_mark_invalid(iop) efhw_page_mark_invalid(&(iop)->p)
++#define efhw_iopage_is_valid(iop) efhw_page_is_valid(&(iop)->p)
++
++/*--------------------------------------------------------------------
++ *
++ * efhw_iopages_t: A set of pages that are contiguous in physical memory.
++ * Directly mapped in the driver, and can be mapped to userlevel. Can also
++ * be accessed by the NIC.
++ *
++ * NB. The O/S may be unwilling to allocate many, or even any of these. So
++ * only use this type where the NIC really needs a physically contiguous
++ * buffer.
++ *
++ *--------------------------------------------------------------------*/
++
++typedef struct {
++ caddr_t kva;
++ unsigned order;
++ dma_addr_t dma_addr;
++} efhw_iopages_t;
++
++static inline caddr_t efhw_iopages_ptr(efhw_iopages_t *p)
++{
++ return p->kva;
++}
++
++static inline unsigned efhw_iopages_pfn(efhw_iopages_t *p)
++{
++ return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
++}
++
++static inline dma_addr_t efhw_iopages_dma_addr(efhw_iopages_t *p)
++{
++ return p->dma_addr;
++}
++
++static inline unsigned efhw_iopages_size(efhw_iopages_t *p)
++{
++ return 1u << (p->order + PAGE_SHIFT);
++}
++
++/* efhw_iopage_t <-> efhw_iopages_t conversions for handling physically
++ * contiguous allocations in iobufsets for iSCSI. This allows the
++ * essential information about contiguous allocations from
++ * efhw_iopages_alloc() to be saved away in the efhw_iopage_t array in an
++ * iobufset. (Changing the iobufset resource to use a union type would
++ * involve a lot of code changes, and make the iobufset's metadata larger
++ * which could be bad as it's supposed to fit into a single page on some
++ * platforms.)
++ */
++static inline void
++efhw_iopage_init_from_iopages(efhw_iopage_t *iopage,
++ efhw_iopages_t *iopages, unsigned pageno)
++{
++ iopage->p.kva = ((unsigned long)efhw_iopages_ptr(iopages))
++ + (pageno * PAGE_SIZE);
++ iopage->dma_addr = efhw_iopages_dma_addr(iopages) +
++ (pageno * PAGE_SIZE);
++}
++
++static inline void
++efhw_iopages_init_from_iopage(efhw_iopages_t *iopages,
++ efhw_iopage_t *iopage, unsigned order)
++{
++ iopages->kva = (caddr_t) efhw_iopage_ptr(iopage);
++ EFHW_ASSERT(iopages->kva);
++ iopages->order = order;
++ iopages->dma_addr = efhw_iopage_dma_addr(iopage);
++}
++
++#endif /* __CI_EFHW_IOPAGE_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/public.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/public.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/public.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/public.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,83 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API of efhw library exported from the SFC
++ * resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_PUBLIC_H__
++#define __CI_EFHW_PUBLIC_H__
++
++#include <ci/efhw/common.h>
++#include <ci/efhw/efhw_types.h>
++
++/*! Returns true if we have some EtherFabric functional units -
++ whether configured or not */
++static inline int efhw_nic_have_functional_units(struct efhw_nic *nic)
++{
++ return nic->efhw_func != 0;
++}
++
++/*! Returns true if the EtherFabric functional units have been configured */
++static inline int efhw_nic_have_hw(struct efhw_nic *nic)
++{
++ return efhw_nic_have_functional_units(nic) && (EFHW_KVA(nic) != 0);
++}
++
++/*! Helper function to allocate the iobuffer needed by an eventq
++ * - it ensures the eventq has the correct alignment for the NIC
++ *
++ * \param rm Event-queue resource manager
++ * \param instance Event-queue instance (index)
++ * \param buf_bytes Requested size of eventq
++ * \return < 0 if iobuffer allocation fails
++ */
++int efhw_nic_event_queue_alloc_iobuffer(struct efhw_nic *nic,
++ struct eventq_resource_hardware *h,
++ int evq_instance, unsigned buf_bytes);
++
++extern void falcon_nic_set_rx_usr_buf_size(struct efhw_nic *,
++ int rx_usr_buf_size);
++
++extern void
++falcon_nic_rx_filter_ctl_set(struct efhw_nic *nic, uint32_t tcp_full,
++ uint32_t tcp_wild,
++ uint32_t udp_full, uint32_t udp_wild);
++
++extern void
++falcon_nic_rx_filter_ctl_get(struct efhw_nic *nic, uint32_t *tcp_full,
++ uint32_t *tcp_wild,
++ uint32_t *udp_full, uint32_t *udp_wild);
++
++#endif /* __CI_EFHW_PUBLIC_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/sysdep.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/sysdep.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efhw/sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efhw/sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,72 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for efhw library.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_SYSDEP_LINUX_H__
++#define __CI_EFHW_SYSDEP_LINUX_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++#include <linux/if_ether.h>
++
++#include <linux/netdevice.h> /* necessary for etherdevice.h on some kernels */
++#include <linux/etherdevice.h>
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)
++static inline int is_local_ether_addr(const u8 *addr)
++{
++ return (0x02 & addr[0]);
++}
++#endif
++
++typedef unsigned long irq_flags_t;
++
++#define spin_lock_destroy(l_) do {} while (0)
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#define HAS_NET_NAMESPACE
++#endif
++
++/* Funny, but linux has round_up for x86 only, defined in
++ * x86-specific header */
++#ifndef round_up
++#define round_up(x, y) (((x) + (y) - 1) & ~((y)-1))
++#endif
++
++#endif /* __CI_EFHW_SYSDEP_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efrm/nic_table.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efrm/nic_table.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efrm/nic_table.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efrm/nic_table.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,98 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for NIC table.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_NIC_TABLE_H__
++#define __CI_EFRM_NIC_TABLE_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efrm/sysdep.h>
++
++/*--------------------------------------------------------------------
++ *
++ * struct efrm_nic_table - top level driver object keeping all NICs -
++ * implemented in driver_object.c
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Comment? */
++struct efrm_nic_table {
++ /*! nics attached to this driver */
++ struct efhw_nic *nic[EFHW_MAX_NR_DEVS];
++ /*! pointer to an arbitrary struct efhw_nic if one exists;
++ * for code which does not care which NIC it wants but
++ * still needs one. Note you cannot assume nic[0] exists. */
++ struct efhw_nic *a_nic;
++ uint32_t nic_count; /*!< number of nics attached to this driver */
++ spinlock_t lock; /*!< lock for table modifications */
++ atomic_t ref_count; /*!< refcount for users of nic table */
++};
++
++/* Resource driver structures used by other drivers as well */
++extern struct efrm_nic_table efrm_nic_table;
++
++static inline void efrm_nic_table_hold(void)
++{
++ atomic_inc(&efrm_nic_table.ref_count);
++}
++
++static inline void efrm_nic_table_rele(void)
++{
++ atomic_dec(&efrm_nic_table.ref_count);
++}
++
++static inline int efrm_nic_table_held(void)
++{
++ return (atomic_read(&efrm_nic_table.ref_count) != 0);
++}
++
++/* Run code block _x multiple times with variable nic set to each
++ * registered NIC in turn.
++ * DO NOT "break" out of this loop early. */
++#define EFRM_FOR_EACH_NIC(_nic_i, _nic) \
++ for ((_nic_i) = (efrm_nic_table_hold(), 0); \
++ (_nic_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \
++ (_nic_i)++) \
++ if (((_nic) = efrm_nic_table.nic[_nic_i]))
++
++#define EFRM_FOR_EACH_NIC_IN_SET(_set, _i, _nic) \
++ for ((_i) = (efrm_nic_table_hold(), 0); \
++ (_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \
++ ++(_i)) \
++ if (((_nic) = efrm_nic_table.nic[_i]) && \
++ efrm_nic_set_read((_set), (_i)))
++
++#endif /* __CI_EFRM_NIC_TABLE_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efrm/sysdep.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efrm/sysdep.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efrm/sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efrm/sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,54 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides Linux-like system-independent API for efrm library.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_SYSDEP_H__
++#define __CI_EFRM_SYSDEP_H__
++
++/* Spinlocks are defined in efhw/sysdep.h */
++#include <ci/efhw/sysdep.h>
++
++#if defined(__linux__) && defined(__KERNEL__)
++
++# include <ci/efrm/sysdep_linux.h>
++
++#else
++
++# include <ci/efrm/sysdep_ci2linux.h>
++
++#endif
++
++#endif /* __CI_EFRM_SYSDEP_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/efrm/sysdep_linux.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efrm/sysdep_linux.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/efrm/sysdep_linux.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/efrm/sysdep_linux.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,248 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ * resource management for Xen backend, OpenOnload, etc
++ * (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for efrm library.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Kfifo API is partially stolen from linux-2.6.22/include/linux/list.h
++ * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
++ *
++ * Developed and maintained by Solarflare Communications:
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ * OKTET Labs Ltd, Russia,
++ * http://oktetlabs.ru, <info@oktetlabs.ru>
++ * by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_SYSDEP_LINUX_H__
++#define __CI_EFRM_SYSDEP_LINUX_H__
++
++#include <linux/version.h>
++#include <linux/list.h>
++#include <linux/vmalloc.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/workqueue.h>
++#include <linux/gfp.h>
++#include <linux/slab.h>
++#include <linux/hardirq.h>
++#include <linux/kernel.h>
++#include <linux/if_ether.h>
++#include <linux/completion.h>
++#include <linux/in.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++/* get roundup_pow_of_two(), which was in kernel.h in early kernel versions */
++#include <linux/log2.h>
++#endif
++
++/********************************************************************
++ *
++ * List API
++ *
++ ********************************************************************/
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++static inline void
++list_replace_init(struct list_head *old, struct list_head *new)
++{
++ new->next = old->next;
++ new->next->prev = new;
++ new->prev = old->prev;
++ new->prev->next = new;
++ INIT_LIST_HEAD(old);
++}
++#endif
++
++static inline struct list_head *list_pop(struct list_head *list)
++{
++ struct list_head *link = list->next;
++ list_del(link);
++ return link;
++}
++
++static inline struct list_head *list_pop_tail(struct list_head *list)
++{
++ struct list_head *link = list->prev;
++ list_del(link);
++ return link;
++}
++
++/********************************************************************
++ *
++ * Workqueue API
++ *
++ ********************************************************************/
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++#define NEED_OLD_WORK_API
++
++/**
++ * The old and new work function prototypes just change
++ * the type of the pointer in the only argument, so it's
++ * safe to cast one function type to the other
++ */
++typedef void (*efrm_old_work_func_t) (void *p);
++
++#undef INIT_WORK
++#define INIT_WORK(_work, _func) \
++ do { \
++ INIT_LIST_HEAD(&(_work)->entry); \
++ (_work)->pending = 0; \
++ PREPARE_WORK((_work), \
++ (efrm_old_work_func_t) (_func), \
++ (_work)); \
++ } while (0)
++
++#endif
++
++/********************************************************************
++ *
++ * Kfifo API
++ *
++ ********************************************************************/
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
++
++#if !defined(RHEL_RELEASE_CODE) || (RHEL_RELEASE_CODE < 1029)
++typedef unsigned gfp_t;
++#endif
++
++#define HAS_NO_KFIFO
++
++struct kfifo {
++ unsigned char *buffer; /* the buffer holding the data */
++ unsigned int size; /* the size of the allocated buffer */
++ unsigned int in; /* data is added at offset (in % size) */
++ unsigned int out; /* data is extracted from off. (out % size) */
++ spinlock_t *lock; /* protects concurrent modifications */
++};
++
++extern struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
++ gfp_t gfp_mask, spinlock_t *lock);
++extern struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask,
++ spinlock_t *lock);
++extern void kfifo_free(struct kfifo *fifo);
++extern unsigned int __kfifo_put(struct kfifo *fifo,
++ unsigned char *buffer, unsigned int len);
++extern unsigned int __kfifo_get(struct kfifo *fifo,
++ unsigned char *buffer, unsigned int len);
++
++/**
++ * kfifo_put - puts some data into the FIFO
++ * @fifo: the fifo to be used.
++ * @buffer: the data to be added.
++ * @len: the length of the data to be added.
++ *
++ * This function copies at most @len bytes from the @buffer into
++ * the FIFO depending on the free space, and returns the number of
++ * bytes copied.
++ */
++static inline unsigned int
++kfifo_put(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
++{
++ unsigned long flags;
++ unsigned int ret;
++
++ spin_lock_irqsave(fifo->lock, flags);
++
++ ret = __kfifo_put(fifo, buffer, len);
++
++ spin_unlock_irqrestore(fifo->lock, flags);
++
++ return ret;
++}
++
++/**
++ * kfifo_get - gets some data from the FIFO
++ * @fifo: the fifo to be used.
++ * @buffer: where the data must be copied.
++ * @len: the size of the destination buffer.
++ *
++ * This function copies at most @len bytes from the FIFO into the
++ * @buffer and returns the number of copied bytes.
++ */
++static inline unsigned int
++kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
++{
++ unsigned long flags;
++ unsigned int ret;
++
++ spin_lock_irqsave(fifo->lock, flags);
++
++ ret = __kfifo_get(fifo, buffer, len);
++
++ /*
++ * optimization: if the FIFO is empty, set the indices to 0
++ * so we don't wrap the next time
++ */
++ if (fifo->in == fifo->out)
++ fifo->in = fifo->out = 0;
++
++ spin_unlock_irqrestore(fifo->lock, flags);
++
++ return ret;
++}
++
++/**
++ * __kfifo_len - returns the number of bytes available in the FIFO, no locking version
++ * @fifo: the fifo to be used.
++ */
++static inline unsigned int __kfifo_len(struct kfifo *fifo)
++{
++ return fifo->in - fifo->out;
++}
++
++/**
++ * kfifo_len - returns the number of bytes available in the FIFO
++ * @fifo: the fifo to be used.
++ */
++static inline unsigned int kfifo_len(struct kfifo *fifo)
++{
++ unsigned long flags;
++ unsigned int ret;
++
++ spin_lock_irqsave(fifo->lock, flags);
++
++ ret = __kfifo_len(fifo);
++
++ spin_unlock_irqrestore(fifo->lock, flags);
++
++ return ret;
++}
++
++#else
++#include <linux/kfifo.h>
++#endif
++
++static inline void kfifo_vfree(struct kfifo *fifo)
++{
++ vfree(fifo->buffer);
++ kfree(fifo);
++}
++
++#endif /* __CI_EFRM_SYSDEP_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/config.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/config.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/config.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/config.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,49 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*! \cidoxg_include_ci_tools */
++
++#ifndef __CI_TOOLS_CONFIG_H__
++#define __CI_TOOLS_CONFIG_H__
++
++
++/**********************************************************************
++ * Debugging.
++ */
++
++#define CI_INCLUDE_ASSERT_VALID 0
++
++/* Set non-zero to allow info about who has allocated what to appear in
++ * /proc/drivers/level5/mem.
++ * However - Note that doing so can lead to segfault when you unload the
++ * driver, and other weirdness. i.e. I don't think the code for is quite
++ * right (written by Oktet, hacked by gel), but it does work well enough to be
++ * useful.
++ */
++#define CI_MEMLEAK_DEBUG_ALLOC_TABLE 0
++
++
++#endif /* __CI_TOOLS_CONFIG_H__ */
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/debug.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/debug.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/debug.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,336 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*! \cidoxg_include_ci_tools */
++
++#ifndef __CI_TOOLS_DEBUG_H__
++#define __CI_TOOLS_DEBUG_H__
++
++#define CI_LOG_E(x) x /* errors */
++#define CI_LOG_W(x) x /* warnings */
++#define CI_LOG_I(x) x /* information */
++#define CI_LOG_V(x) x /* verbose */
++
++/* Build time asserts. We paste the line number into the type name
++ * so that the macro can be used more than once per file even if the
++ * compiler objects to multiple identical typedefs. Collisions
++ * between use in different header files is still possible. */
++#ifndef CI_BUILD_ASSERT
++#define __CI_BUILD_ASSERT_NAME(_x) __CI_BUILD_ASSERT_ILOATHECPP(_x)
++#define __CI_BUILD_ASSERT_ILOATHECPP(_x) __CI_BUILD_ASSERT__ ##_x
++#define CI_BUILD_ASSERT(e)\
++ typedef char __CI_BUILD_ASSERT_NAME(__LINE__)[(e)?1:-1]
++#endif
++
++
++#ifdef NDEBUG
++
++# define _ci_check(exp, file, line)
++# define _ci_assert2(e, x, y, file, line)
++# define _ci_assert(exp, file, line)
++# define _ci_assert_equal(exp1, exp2, file, line)
++# define _ci_assert_equiv(exp1, exp2, file, line)
++# define _ci_assert_nequal(exp1, exp2, file, line)
++# define _ci_assert_le(exp1, exp2, file, line)
++# define _ci_assert_lt(exp1, exp2, file, line)
++# define _ci_assert_ge(exp1, exp2, file, line)
++# define _ci_assert_gt(exp1, exp2, file, line)
++# define _ci_assert_impl(exp1, exp2, file, line)
++
++# define _ci_verify(exp, file, line) \
++ do { \
++ (void)(exp); \
++ } while (0)
++
++# define CI_DEBUG_TRY(exp) \
++ do { \
++ (void)(exp); \
++ } while (0)
++
++#define CI_TRACE(exp,fmt)
++#define CI_TRACE_INT(integer)
++#define CI_TRACE_INT32(integer)
++#define CI_TRACE_INT64(integer)
++#define CI_TRACE_UINT(integer)
++#define CI_TRACE_UINT32(integer)
++#define CI_TRACE_UINT64(integer)
++#define CI_TRACE_HEX(integer)
++#define CI_TRACE_HEX32(integer)
++#define CI_TRACE_HEX64(integer)
++#define CI_TRACE_PTR(pointer)
++#define CI_TRACE_STRING(string)
++#define CI_TRACE_MAC(mac)
++#define CI_TRACE_IP(ip_be32)
++#define CI_TRACE_ARP(arp_pkt)
++
++#else
++
++# define _CI_ASSERT_FMT "\nfrom %s:%d"
++
++# define _ci_check(exp, file, line) \
++ do { \
++ if (CI_UNLIKELY(!(exp))) \
++ ci_warn(("ci_check(%s)"_CI_ASSERT_FMT, #exp, \
++ (file), (line))); \
++ } while (0)
++
++/*
++ * NOTE: ci_fail() emits the file and line where the assert is actually
++ * coded.
++ */
++
++# define _ci_assert(exp, file, line) \
++ do { \
++ if (CI_UNLIKELY(!(exp))) \
++ ci_fail(("ci_assert(%s)"_CI_ASSERT_FMT, #exp, \
++ (file), (line))); \
++ } while (0)
++
++# define _ci_assert2(e, x, y, file, line) do { \
++ if(CI_UNLIKELY( ! (e) )) \
++ ci_fail(("ci_assert(%s)\nwhere [%s=%"CI_PRIx64"] " \
++ "[%s=%"CI_PRIx64"]\nat %s:%d\nfrom %s:%d", #e \
++ , #x, (ci_uint64)(ci_uintptr_t)(x) \
++ , #y, (ci_uint64)(ci_uintptr_t)(y), \
++ __FILE__, __LINE__, (file), (line))); \
++ } while (0)
++
++# define _ci_verify(exp, file, line) \
++ do { \
++ if (CI_UNLIKELY(!(exp))) \
++ ci_fail(("ci_verify(%s)"_CI_ASSERT_FMT, #exp, \
++ (file), (line))); \
++ } while (0)
++
++# define _ci_assert_equal(x, y, f, l) _ci_assert2((x)==(y), x, y, (f), (l))
++# define _ci_assert_nequal(x, y, f, l) _ci_assert2((x)!=(y), x, y, (f), (l))
++# define _ci_assert_le(x, y, f, l) _ci_assert2((x)<=(y), x, y, (f), (l))
++# define _ci_assert_lt(x, y, f, l) _ci_assert2((x)< (y), x, y, (f), (l))
++# define _ci_assert_ge(x, y, f, l) _ci_assert2((x)>=(y), x, y, (f), (l))
++# define _ci_assert_gt(x, y, f, l) _ci_assert2((x)> (y), x, y, (f), (l))
++# define _ci_assert_or(x, y, f, l) _ci_assert2((x)||(y), x, y, (f), (l))
++# define _ci_assert_impl(x, y, f, l) _ci_assert2(!(x) || (y), x, y, (f), (l))
++# define _ci_assert_equiv(x, y, f, l) _ci_assert2(!(x)== !(y), x, y, (f), (l))
++
++#define _ci_assert_equal_msg(exp1, exp2, msg, file, line) \
++ do { \
++ if (CI_UNLIKELY((exp1)!=(exp2))) \
++ ci_fail(("ci_assert_equal_msg(%s == %s) were " \
++ "(%"CI_PRIx64":%"CI_PRIx64") with msg[%c%c%c%c]" \
++ _CI_ASSERT_FMT, #exp1, #exp2, \
++ (ci_uint64)(ci_uintptr_t)(exp1), \
++ (ci_uint64)(ci_uintptr_t)(exp2), \
++ (((ci_uint32)msg) >> 24) && 0xff, \
++ (((ci_uint32)msg) >> 16) && 0xff, \
++ (((ci_uint32)msg) >> 8 ) && 0xff, \
++ (((ci_uint32)msg) ) && 0xff, \
++ (file), (line))); \
++ } while (0)
++
++# define CI_DEBUG_TRY(exp) CI_TRY(exp)
++
++#define CI_TRACE(exp,fmt) \
++ ci_log("%s:%d:%s] " #exp "=" fmt, \
++ __FILE__, __LINE__, __FUNCTION__, (exp))
++
++
++#define CI_TRACE_INT(integer) \
++ ci_log("%s:%d:%s] " #integer "=%d", \
++ __FILE__, __LINE__, __FUNCTION__, (integer))
++
++
++#define CI_TRACE_INT32(integer) \
++ ci_log("%s:%d:%s] " #integer "=%d", \
++ __FILE__, __LINE__, __FUNCTION__, ((ci_int32)integer))
++
++
++#define CI_TRACE_INT64(integer) \
++ ci_log("%s:%d:%s] " #integer "=%lld", \
++ __FILE__, __LINE__, __FUNCTION__, ((ci_int64)integer))
++
++
++#define CI_TRACE_UINT(integer) \
++ ci_log("%s:%d:%s] " #integer "=%ud", \
++ __FILE__, __LINE__, __FUNCTION__, (integer))
++
++
++#define CI_TRACE_UINT32(integer) \
++ ci_log("%s:%d:%s] " #integer "=%ud", \
++ __FILE__, __LINE__, __FUNCTION__, ((ci_uint32)integer))
++
++
++#define CI_TRACE_UINT64(integer) \
++ ci_log("%s:%d:%s] " #integer "=%ulld", \
++ __FILE__, __LINE__, __FUNCTION__, ((ci_uint64)integer))
++
++
++#define CI_TRACE_HEX(integer) \
++ ci_log("%s:%d:%s] " #integer "=0x%x", \
++ __FILE__, __LINE__, __FUNCTION__, (integer))
++
++
++#define CI_TRACE_HEX32(integer) \
++ ci_log("%s:%d:%s] " #integer "=0x%x", \
++ __FILE__, __LINE__, __FUNCTION__, ((ci_uint32)integer))
++
++
++#define CI_TRACE_HEX64(integer) \
++ ci_log("%s:%d:%s] " #integer "=0x%llx", \
++ __FILE__, __LINE__, __FUNCTION__, ((ci_uint64)integer))
++
++
++#define CI_TRACE_PTR(pointer) \
++ ci_log("%s:%d:%s] " #pointer "=0x%p", \
++ __FILE__, __LINE__, __FUNCTION__, (pointer))
++
++
++#define CI_TRACE_STRING(string) \
++ ci_log("%s:%d:%s] " #string "=%s", \
++ __FILE__, __LINE__, __FUNCTION__, (string))
++
++
++#define CI_TRACE_MAC(mac) \
++ ci_log("%s:%d:%s] " #mac "=" CI_MAC_PRINTF_FORMAT, \
++ __FILE__, __LINE__, __FUNCTION__, CI_MAC_PRINTF_ARGS(mac))
++
++
++#define CI_TRACE_IP(ip_be32) \
++ ci_log("%s:%d:%s] " #ip_be32 "=" CI_IP_PRINTF_FORMAT, __FILE__, \
++ __LINE__, __FUNCTION__, CI_IP_PRINTF_ARGS(&(ip_be32)))
++
++
++#define CI_TRACE_ARP(arp_pkt) \
++ ci_log("%s:%d:%s]\n"CI_ARP_PRINTF_FORMAT, \
++ __FILE__, __LINE__, __FUNCTION__, CI_ARP_PRINTF_ARGS(arp_pkt))
++
++#endif /* NDEBUG */
++
++#define ci_check(exp) \
++ _ci_check(exp, __FILE__, __LINE__)
++
++#define ci_assert(exp) \
++ _ci_assert(exp, __FILE__, __LINE__)
++
++#define ci_verify(exp) \
++ _ci_verify(exp, __FILE__, __LINE__)
++
++#define ci_assert_equal(exp1, exp2) \
++ _ci_assert_equal(exp1, exp2, __FILE__, __LINE__)
++
++#define ci_assert_equal_msg(exp1, exp2, msg) \
++ _ci_assert_equal_msg(exp1, exp2, msg, __FILE__, __LINE__)
++
++#define ci_assert_nequal(exp1, exp2) \
++ _ci_assert_nequal(exp1, exp2, __FILE__, __LINE__)
++
++#define ci_assert_le(exp1, exp2) \
++ _ci_assert_le(exp1, exp2, __FILE__, __LINE__)
++
++#define ci_assert_lt(exp1, exp2) \
++ _ci_assert_lt(exp1, exp2, __FILE__, __LINE__)
++
++#define ci_assert_ge(exp1, exp2) \
++ _ci_assert_ge(exp1, exp2, __FILE__, __LINE__)
++
++#define ci_assert_gt(exp1, exp2) \
++ _ci_assert_gt(exp1, exp2, __FILE__, __LINE__)
++
++#define ci_assert_impl(exp1, exp2) \
++ _ci_assert_impl(exp1, exp2, __FILE__, __LINE__)
++
++#define ci_assert_equiv(exp1, exp2) \
++ _ci_assert_equiv(exp1, exp2, __FILE__, __LINE__)
++
++
++#define CI_TEST(exp) \
++ do{ \
++ if( CI_UNLIKELY(!(exp)) ) \
++ ci_fail(("CI_TEST(%s)", #exp)); \
++ }while(0)
++
++
++#define CI_TRY(exp) \
++ do{ \
++ int _trc; \
++ _trc=(exp); \
++ if( CI_UNLIKELY(_trc < 0) ) \
++ ci_sys_fail(#exp, _trc); \
++ }while(0)
++
++
++#define CI_TRY_RET(exp) \
++ do{ \
++ int _trc; \
++ _trc=(exp); \
++ if( CI_UNLIKELY(_trc < 0) ) { \
++ ci_log("%s returned %d at %s:%d", #exp, _trc, __FILE__, __LINE__); \
++ return _trc; \
++ } \
++ }while(0)
++
++#define CI_LOGLEVEL_TRY_RET(logfn, exp) \
++ do{ \
++ int _trc; \
++ _trc=(exp); \
++ if( CI_UNLIKELY(_trc < 0) ) { \
++ logfn (ci_log("%s returned %d at %s:%d", #exp, _trc, __FILE__, __LINE__)); \
++ return _trc; \
++ } \
++ }while(0)
++
++
++#define CI_SOCK_TRY(exp) \
++ do{ \
++ ci_sock_err_t _trc; \
++ _trc=(exp); \
++ if( CI_UNLIKELY(!ci_sock_errok(_trc)) ) \
++ ci_sys_fail(#exp, _trc.val); \
++ }while(0)
++
++
++#define CI_SOCK_TRY_RET(exp) \
++ do{ \
++ ci_sock_err_t _trc; \
++ _trc=(exp); \
++ if( CI_UNLIKELY(!ci_sock_errok(_trc)) ) { \
++ ci_log("%s returned %d at %s:%d", #exp, _trc.val, __FILE__, __LINE__); \
++ return ci_sock_errcode(_trc); \
++ } \
++ }while(0)
++
++
++#define CI_SOCK_TRY_SOCK_RET(exp) \
++ do{ \
++ ci_sock_err_t _trc; \
++ _trc=(exp); \
++ if( CI_UNLIKELY(!ci_sock_errok(_trc)) ) { \
++ ci_log("%s returned %d at %s:%d", #exp, _trc.val, __FILE__, __LINE__); \
++ return _trc; \
++ } \
++ }while(0)
++
++#endif /* __CI_TOOLS_DEBUG_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/log.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/log.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/log.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/log.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,262 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr
++ * \brief Functions for logging and pretty-printing.
++ * \date 2002/08/07
++ */
++
++/*! \cidoxg_include_ci_tools */
++
++#ifndef __CI_TOOLS_LOG_H__
++#define __CI_TOOLS_LOG_H__
++
++#include <stdarg.h>
++
++
++/**********************************************************************
++ * Logging.
++ */
++
++/* size of internal log buffer */
++#define CI_LOG_MAX_LINE 512
++/* uses of ci_log must ensure that all trace messages are shorter than this */
++#define CI_LOG_MAX_MSG_LENGTH (CI_LOG_MAX_LINE-50)
++
++extern void ci_vlog(const char* fmt, va_list args) CI_HF;
++extern void ci_log(const char* fmt, ...) CI_PRINTF_LIKE(1,2) CI_HF;
++
++ /*! Set the prefix for log messages.
++ **
++ ** Uses the storage pointed to by \em prefix. Therefore \em prefix must
++ ** be allocated on the heap, or statically.
++ */
++extern void ci_set_log_prefix(const char* prefix) CI_HF;
++
++typedef void (*ci_log_fn_t)(const char* msg);
++extern ci_log_fn_t ci_log_fn CI_HV;
++
++/* Log functions. */
++extern void ci_log_null(const char* msg) CI_HF;
++extern void ci_log_stderr(const char* msg) CI_HF;
++extern void ci_log_stdout(const char* msg) CI_HF;
++extern void ci_log_syslog(const char* msg) CI_HF;
++
++/*! Call the following to install special logging behaviours. */
++extern void ci_log_buffer_till_fail(void) CI_HF;
++extern void ci_log_buffer_till_exit(void) CI_HF;
++
++extern void __ci_log_unique(const char* msg) CI_HF;
++extern ci_log_fn_t __ci_log_unique_fn CI_HV;
++ci_inline void ci_log_uniquify(void) {
++ if( ci_log_fn != __ci_log_unique ) {
++ __ci_log_unique_fn = ci_log_fn;
++ ci_log_fn = __ci_log_unique;
++ }
++}
++
++extern void ci_log_file(const char* msg) CI_HF;
++extern int ci_log_file_fd CI_HV;
++
++extern void __ci_log_nth(const char* msg) CI_HF;
++extern ci_log_fn_t __ci_log_nth_fn CI_HV;
++extern int ci_log_nth_n CI_HV; /* default 100 */
++ci_inline void ci_log_nth(void) {
++ if( ci_log_fn != __ci_log_nth ) {
++ __ci_log_nth_fn = ci_log_fn;
++ ci_log_fn = __ci_log_nth;
++ }
++}
++
++extern int ci_log_level CI_HV;
++
++extern int ci_log_options CI_HV;
++#define CI_LOG_PID 0x1
++#define CI_LOG_TID 0x2
++#define CI_LOG_TIME 0x4
++#define CI_LOG_DELTA 0x8
++
++/**********************************************************************
++ * Used to define which mode we are in
++ */
++#if (defined(_WIN32) && !defined(__KERNEL__))
++typedef enum {
++ ci_log_md_NULL=0,
++ ci_log_md_ioctl,
++ ci_log_md_stderr,
++ ci_log_md_stdout,
++ ci_log_md_file,
++ ci_log_md_serial,
++ ci_log_md_syslog,
++ ci_log_md_pidfile
++} ci_log_mode_t;
++extern ci_log_mode_t ci_log_mode;
++#endif
++
++/**********************************************************************
++ * Pretty-printing.
++ */
++
++extern char ci_printable_char(char c) CI_HF;
++
++extern void (*ci_hex_dump_formatter)(char* buf, const ci_octet* s,
++ int i, int off, int len) CI_HV;
++extern void ci_hex_dump_format_octets(char*,const ci_octet*,int,int,int) CI_HF;
++extern void ci_hex_dump_format_dwords(char*,const ci_octet*,int,int,int) CI_HF;
++
++extern void ci_hex_dump_row(char* buf, volatile const void* s, int len,
++ ci_ptr_arith_t address) CI_HF;
++ /*!< A row contains up to 16 bytes. Row starts at [address & 15u], so
++ ** therefore [len + (address & 15u)] must be <= 16.
++ */
++
++extern void ci_hex_dump(ci_log_fn_t, volatile const void*,
++ int len, ci_ptr_arith_t address) CI_HF;
++
++extern int ci_hex_dump_to_raw(const char* src_hex, void* buf,
++ unsigned* addr_out_opt, int* skip) CI_HF;
++ /*!< Recovers raw data from a single line of a hex dump. [buf] must be at
++ ** least 16 bytes long. Returns the number of bytes written to [buf] (in
++ ** range 1 -> 16), or -1 if [src_hex] doesn't contain hex data. Does not
++ ** cope with missing bytes at the start of a line.
++ */
++
++extern int ci_format_eth_addr(char* buf, const void* eth_mac_addr,
++ char sep) CI_HF;
++ /*!< This will write 18 characters to <buf> including terminating null.
++ ** Returns number of bytes written excluding null. If [sep] is zero, ':'
++ ** is used.
++ */
++
++extern int ci_parse_eth_addr(void* eth_mac_addr,
++ const char* str, char sep) CI_HF;
++ /*!< If [sep] is zero, absolutely any separator is accepted (even
++ ** inconsistent separators). Returns 0 on success, -1 on error.
++ */
++
++extern int ci_format_ip4_addr(char* buf, unsigned addr_be32) CI_HF;
++ /*!< Formats the IP address (in network endian) in dotted-quad. Returns
++ ** the number of bytes written (up to 15), excluding the null. [buf]
++ ** must be at least 16 bytes long.
++ */
++
++
++/**********************************************************************
++ * Error checking.
++ */
++
++extern void (*ci_fail_stop_fn)(void) CI_HV;
++
++extern void ci_fail_stop(void) CI_HF;
++extern void ci_fail_hang(void) CI_HF;
++extern void ci_fail_bomb(void) CI_HF;
++extern void ci_backtrace(void) CI_HF;
++
++#if defined __linux__ && !defined __KERNEL__
++extern void ci_fail_abort (void) CI_HF;
++#endif
++
++#ifdef __GNUC__
++extern void
++__ci_fail(const char*, ...) CI_PRINTF_LIKE(1,2) CI_HF;
++#else
++# if _PREFAST_
++ extern void _declspec(noreturn) __ci_fail(const char* fmt, ...);
++# else
++ extern void __ci_fail(const char* fmt, ...);
++# endif
++
++#endif
++
++#define ci_warn(x) \
++ do{ ci_log("WARN at %s:%d", __FILE__, __LINE__); }while(0)
++
++#define ci_fail(x) \
++ do{ ci_log("FAIL at %s:%d", __FILE__, __LINE__); __ci_fail x; }while(0)
++
++extern void __ci_sys_fail(const char* fn, int rc,
++ const char* file, int line) CI_HF;
++#define ci_sys_fail(fn, rc) __ci_sys_fail(fn, rc, __FILE__, __LINE__)
++
++/**********************************************************************
++ * Logging to buffer (src/citools/log_buffer.c)
++ */
++
++/*! Divert ci_log() messages to the log buffer
++ * normally they go to the system console */
++extern void ci_log_buffer_till_fail(void) CI_HF;
++
++/*! Dump the contents of the log buffer to the system console */
++extern void ci_log_buffer_dump(void) CI_HF;
++
++
++/**********************************************************************
++ * Some useful pretty-printing.
++ */
++
++#ifdef __linux__
++# define CI_SOCKCALL_FLAGS_FMT "%s%s%s%s%s%s%s%s%s%s%s"
++
++# define CI_SOCKCALL_FLAGS_PRI_ARG(x) \
++ (((x) & MSG_OOB ) ? "OOB " :""), \
++ (((x) & MSG_PEEK ) ? "PEEK " :""), \
++ (((x) & MSG_DONTROUTE ) ? "DONTROUTE " :""), \
++ (((x) & MSG_EOR ) ? "EOR " :""), \
++ (((x) & MSG_CTRUNC ) ? "CTRUNC " :""), \
++ (((x) & MSG_TRUNC ) ? "TRUNC " :""), \
++ (((x) & MSG_WAITALL ) ? "WAITALL " :""), \
++ (((x) & MSG_DONTWAIT ) ? "DONTWAIT " :""), \
++ (((x) & MSG_NOSIGNAL ) ? "NOSIGNAL " :""), \
++ (((x) & MSG_ERRQUEUE ) ? "ERRQUEUE " :""), \
++ (((x) & MSG_CONFIRM ) ? "CONFIRM " :"")
++#endif
++
++#ifdef _WIN32
++# define CI_SOCKCALL_FLAGS_FMT "%s%s%s"
++
++# define CI_SOCKCALL_FLAGS_PRI_ARG(x) \
++ (((x) & MSG_OOB ) ? "OOB " :""), \
++ (((x) & MSG_PEEK ) ? "PEEK " :""), \
++ (((x) & MSG_DONTROUTE ) ? "DONTROUTE " :"")
++#endif
++
++#ifdef __sun__
++# define CI_SOCKCALL_FLAGS_FMT "%s%s%s%s%s%s%s%s%s"
++
++# define CI_SOCKCALL_FLAGS_PRI_ARG(x) \
++ (((x) & MSG_OOB ) ? "OOB " :""), \
++ (((x) & MSG_PEEK ) ? "PEEK " :""), \
++ (((x) & MSG_DONTROUTE ) ? "DONTROUTE " :""), \
++ (((x) & MSG_EOR ) ? "EOR " :""), \
++ (((x) & MSG_CTRUNC ) ? "CTRUNC " :""), \
++ (((x) & MSG_TRUNC ) ? "TRUNC " :""), \
++ (((x) & MSG_WAITALL ) ? "WAITALL " :""), \
++ (((x) & MSG_DONTWAIT ) ? "DONTWAIT " :""), \
++ (((x) & MSG_NOTIFICATION) ? "NOTIFICATION" :"")
++#endif
++
++#endif /* __CI_TOOLS_LOG_H__ */
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/platform/gcc_x86.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/platform/gcc_x86.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/platform/gcc_x86.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/platform/gcc_x86.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,361 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*! \cidoxg_include_ci_tools_platform */
++
++#ifndef __CI_TOOLS_GCC_X86_H__
++#define __CI_TOOLS_GCC_X86_H__
++
++
++/**********************************************************************
++ * Free-running cycle counters.
++ */
++
++#define CI_HAVE_FRC64
++#define CI_HAVE_FRC32
++
++#define ci_frc32(pval) __asm__ __volatile__("rdtsc" : "=a" (*pval) : : "edx")
++
++#if defined(__x86_64__)
++ci_inline void ci_frc64(ci_uint64* pval) {
++ /* temp fix until we figure how to get this out in one bite */
++ ci_uint64 low, high;
++ __asm__ __volatile__("rdtsc" : "=a" (low) , "=d" (high));
++ *pval = (high << 32) | low;
++}
++
++#else
++#define ci_frc64(pval) __asm__ __volatile__("rdtsc" : "=A" (*pval))
++#endif
++
++#define ci_frc_flush() /* ?? Need a pipeline barrier. */
++
++
++/**********************************************************************
++ * Atomic integer.
++ */
++
++/*
++** int ci_atomic_read(a) { return a->n; }
++** void ci_atomic_set(a, v) { a->n = v; }
++** void ci_atomic_inc(a) { ++a->n; }
++** void ci_atomic_dec(a) { --a->n; }
++** int ci_atomic_inc_and_test(a) { return ++a->n == 0; }
++** int ci_atomic_dec_and_test(a) { return --a->n == 0; }
++** void ci_atomic_and(a, v) { a->n &= v; }
++** void ci_atomic_or(a, v) { a->n |= v; }
++*/
++
++typedef struct { volatile ci_int32 n; } ci_atomic_t;
++
++#define CI_ATOMIC_INITIALISER(i) {(i)}
++
++static inline ci_int32 ci_atomic_read(const ci_atomic_t* a) { return a->n; }
++static inline void ci_atomic_set(ci_atomic_t* a, int v) { a->n = v; ci_wmb(); }
++
++static inline void ci_atomic_inc(ci_atomic_t* a)
++{ __asm__ __volatile__("lock; incl %0" : "+m" (a->n)); }
++
++
++static inline void ci_atomic_dec(ci_atomic_t* a)
++{ __asm__ __volatile__("lock; decl %0" : "+m" (a->n)); }
++
++static inline int ci_atomic_inc_and_test(ci_atomic_t* a) {
++ char r;
++ __asm__ __volatile__("lock; incl %0; sete %1"
++ : "+m" (a->n), "=qm" (r));
++ return r;
++}
++
++static inline int ci_atomic_dec_and_test(ci_atomic_t* a) {
++ char r;
++ __asm__ __volatile__("lock; decl %0; sete %1"
++ : "+m" (a->n), "=qm" (r));
++ return r;
++}
++
++ci_inline int
++ci_atomic_xadd (ci_atomic_t *a, int v) {
++ __asm__ ("lock xadd %0, %1" : "=r" (v), "+m" (a->n) : "0" (v));
++ return v;
++}
++ci_inline int
++ci_atomic_xchg (ci_atomic_t *a, int v) {
++ __asm__ ("lock xchg %0, %1" : "=r" (v), "+m" (a->n) : "0" (v));
++ return v;
++}
++
++ci_inline void ci_atomic32_or(volatile ci_uint32* p, ci_uint32 mask)
++{ __asm__ __volatile__("lock; orl %1, %0" : "+m" (*p) : "ir" (mask)); }
++
++ci_inline void ci_atomic32_and(volatile ci_uint32* p, ci_uint32 mask)
++{ __asm__ __volatile__("lock; andl %1, %0" : "+m" (*p) : "ir" (mask)); }
++
++ci_inline void ci_atomic32_add(volatile ci_uint32* p, ci_uint32 v)
++{ __asm__ __volatile__("lock; addl %1, %0" : "+m" (*p) : "ir" (v)); }
++
++#define ci_atomic_or(a, v) ci_atomic32_or ((ci_uint32*) &(a)->n, (v))
++#define ci_atomic_and(a, v) ci_atomic32_and((ci_uint32*) &(a)->n, (v))
++#define ci_atomic_add(a, v) ci_atomic32_add((ci_uint32*) &(a)->n, (v))
++
++extern int ci_glibc_uses_nptl (void) CI_HF;
++extern int ci_glibc_nptl_broken(void) CI_HF;
++extern int ci_glibc_gs_get_is_multihreaded_offset (void) CI_HF;
++extern int ci_glibc_gs_is_multihreaded_offset CI_HV;
++
++#if !defined(__x86_64__)
++#ifdef __GLIBC__
++/* Returns non-zero if the calling process might be mulithreaded, returns 0 if
++ * it definitely isn't (i.e. if reimplementing this function for other
++ * architectures and platforms, you can safely just return 1).
++ */
++static inline int ci_is_multithreaded (void) {
++
++ while (1) {
++ if (ci_glibc_gs_is_multihreaded_offset >= 0) {
++ /* NPTL keeps a variable that tells us this hanging off gs (i.e. in thread-
++ * local storage); just return this
++ */
++ int r;
++ __asm__ __volatile__ ("movl %%gs:(%1), %0"
++ : "=r" (r)
++ : "r" (ci_glibc_gs_is_multihreaded_offset));
++ return r;
++ }
++
++ if (ci_glibc_gs_is_multihreaded_offset == -2) {
++ /* This means we've already determined that the libc version is NOT good
++ * for our funky "is multithreaded" hack
++ */
++ return 1;
++ }
++
++ /* If we get here, it means this is the first time the function has been
++ * called -- detect the libc version and go around again.
++ */
++ ci_glibc_gs_is_multihreaded_offset = ci_glibc_gs_get_is_multihreaded_offset ();
++
++ /* Go around again. We do the test here rather than at the top so that we go
++ * quicker in the common the case
++ */
++ }
++}
++
++#else /* def __GLIBC__ */
++
++#define ci_is_multithreaded() 1 /* ?? Is the the POSIX way of finding out */
++ /* whether the appication is single */
++ /* threaded? */
++
++#endif /* def __GLIBC__ */
++
++#else /* defined __x86_64__ */
++
++static inline int ci_is_multithreaded (void) {
++ /* Now easy way to tell on x86_64; so assume we're multithreaded */
++ return 1;
++}
++
++#endif /* defined __x86_64__ */
++
++
++/**********************************************************************
++ * Compare and swap.
++ */
++
++#define CI_HAVE_COMPARE_AND_SWAP
++
++ci_inline int ci_cas32_succeed(volatile ci_int32* p, ci_int32 oldval,
++ ci_int32 newval) {
++ char ret;
++ ci_int32 prevval;
++ __asm__ __volatile__("lock; cmpxchgl %3, %1; sete %0"
++ : "=q"(ret), "+m"(*p), "=a"(prevval)
++ : "r"(newval), "a"(oldval));
++ return ret;
++}
++
++ci_inline int ci_cas32_fail(volatile ci_int32* p, ci_int32 oldval,
++ ci_int32 newval) {
++ char ret;
++ ci_int32 prevval;
++ __asm__ __volatile__("lock; cmpxchgl %3, %1; setne %0"
++ : "=q"(ret), "+m"(*p), "=a"(prevval)
++ : "r"(newval), "a"(oldval));
++ return ret;
++}
++
++#ifdef __x86_64__
++ci_inline int ci_cas64_succeed(volatile ci_int64* p, ci_int64 oldval,
++ ci_int64 newval) {
++ char ret;
++ ci_int64 prevval;
++ __asm__ __volatile__("lock; cmpxchgq %3, %1; sete %0"
++ : "=q"(ret), "+m"(*p), "=a"(prevval)
++ : "r"(newval), "a"(oldval));
++ return ret;
++}
++
++ci_inline int ci_cas64_fail(volatile ci_int64* p, ci_int64 oldval,
++ ci_int64 newval) {
++ char ret;
++ ci_int64 prevval;
++ __asm__ __volatile__("lock; cmpxchgq %3, %1; setne %0"
++ : "=q"(ret), "+m"(*p), "=a"(prevval)
++ : "r"(newval), "a"(oldval));
++ return ret;
++}
++#endif
++
++ci_inline int ci_cas32u_succeed(volatile ci_uint32* p, ci_uint32 oldval, ci_uint32 newval) {
++ char ret;
++ ci_uint32 prevval;
++ __asm__ __volatile__("lock; cmpxchgl %3, %1; sete %0"
++ : "=q"(ret), "+m"(*p), "=a"(prevval)
++ : "r"(newval), "a"(oldval));
++ return ret;
++}
++
++ci_inline int ci_cas32u_fail(volatile ci_uint32* p, ci_uint32 oldval, ci_uint32 newval) {
++ char ret;
++ ci_uint32 prevval;
++ __asm__ __volatile__("lock; cmpxchgl %3, %1; setne %0"
++ : "=q"(ret), "+m"(*p), "=a"(prevval)
++ : "r"(newval), "a"(oldval));
++ return ret;
++}
++
++ci_inline int ci_cas64u_succeed(volatile ci_uint64* p, ci_uint64 oldval,
++ ci_uint64 newval) {
++ char ret;
++ ci_uint64 prevval;
++ __asm__ __volatile__("lock; cmpxchgq %3, %1; sete %0"
++ : "=q"(ret), "+m"(*p), "=a"(prevval)
++ : "r"(newval), "a"(oldval));
++ return ret;
++}
++
++ci_inline int ci_cas64u_fail(volatile ci_uint64* p, ci_uint64 oldval,
++ ci_uint64 newval) {
++ char ret;
++ ci_uint64 prevval;
++ __asm__ __volatile__("lock; cmpxchgq %3, %1; setne %0"
++ : "=q"(ret), "+m"(*p), "=a"(prevval)
++ : "r"(newval), "a"(oldval));
++ return ret;
++}
++
++#ifdef __x86_64__
++
++# define ci_cas_uintptr_succeed(p,o,n) \
++ ci_cas64u_succeed((volatile ci_uint64*) (p), (o), (n))
++# define ci_cas_uintptr_fail(p,o,n) \
++ ci_cas64u_fail((volatile ci_uint64*) (p), (o), (n))
++
++#else
++
++# define ci_cas_uintptr_succeed(p,o,n) \
++ ci_cas32u_succeed((volatile ci_uint32*) (p), (o), (n))
++# define ci_cas_uintptr_fail(p,o,n) \
++ ci_cas32u_fail((volatile ci_uint32*) (p), (o), (n))
++
++#endif
++
++
++/**********************************************************************
++ * Atomic bit field.
++ */
++
++typedef ci_uint32 ci_bits;
++#define CI_BITS_N 32u
++
++#define CI_BITS_DECLARE(name, n) \
++ ci_bits name[((n) + CI_BITS_N - 1u) / CI_BITS_N]
++
++ci_inline void ci_bits_clear_all(volatile ci_bits* b, int n_bits)
++{ memset((void*) b, 0, (n_bits+CI_BITS_N-1u) / CI_BITS_N * sizeof(ci_bits)); }
++
++ci_inline void ci_bit_set(volatile ci_bits* b, int i) {
++ __asm__ __volatile__("lock; btsl %1, %0"
++ : "=m" (*b)
++ : "Ir" (i));
++}
++
++ci_inline void ci_bit_clear(volatile ci_bits* b, int i) {
++ __asm__ __volatile__("lock; btrl %1, %0"
++ : "=m" (*b)
++ : "Ir" (i));
++}
++
++ci_inline int ci_bit_test(volatile ci_bits* b, int i) {
++ char rc;
++ __asm__("btl %2, %1; setc %0"
++ : "=r" (rc)
++ : "m" (*b), "Ir" (i));
++ return rc;
++}
++
++ci_inline int ci_bit_test_and_set(volatile ci_bits* b, int i) {
++ char rc;
++ __asm__ __volatile__("lock; btsl %2, %1; setc %0"
++ : "=r" (rc), "+m" (*b)
++ : "Ir" (i));
++ return rc;
++}
++
++ci_inline int ci_bit_test_and_clear(volatile ci_bits* b, int i) {
++ char rc;
++ __asm__ __volatile__("lock; btrl %2, %1; setc %0"
++ : "=r" (rc), "+m" (*b)
++ : "Ir" (i));
++ return rc;
++}
++
++/* These mask ops only work within a single ci_bits word. */
++#define ci_bit_mask_set(b,m) ci_atomic32_or((b), (m))
++#define ci_bit_mask_clear(b,m) ci_atomic32_and((b), ~(m))
++
++
++/**********************************************************************
++ * Misc.
++ */
++
++#if __GNUC__ >= 3
++# define ci_spinloop_pause() __asm__("pause")
++#else
++# define ci_spinloop_pause() __asm__(".byte 0xf3, 0x90")
++#endif
++
++
++#define CI_HAVE_ADDC32
++#define ci_add_carry32(sum, v) __asm__("addl %1, %0 ;" \
++ "adcl $0, %0 ;" \
++ : "=r" (sum) \
++ : "g" ((ci_uint32) v), "0" (sum))
++
++
++#endif /* __CI_TOOLS_GCC_X86_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/platform/linux_kernel.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/platform/linux_kernel.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/platform/linux_kernel.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/platform/linux_kernel.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,362 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++
++/*! \cidoxg_include_ci_tools_platform */
++
++#ifndef __CI_TOOLS_LINUX_KERNEL_H__
++#define __CI_TOOLS_LINUX_KERNEL_H__
++
++/**********************************************************************
++ * Need to know the kernel version.
++ */
++
++#ifndef LINUX_VERSION_CODE
++# include <linux/version.h>
++# ifndef UTS_RELEASE
++ /* 2.6.18 onwards defines UTS_RELEASE in a separate header */
++# include <linux/utsrelease.h>
++# endif
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) || \
++ LINUX_VERSION_CODE >= KERNEL_VERSION(2,7,0)
++# error "Linux 2.6 required"
++#endif
++
++
++#include <linux/slab.h> /* kmalloc / kfree */
++#include <linux/vmalloc.h> /* vmalloc / vfree */
++#include <linux/interrupt.h>/* in_interrupt() */
++#include <linux/in.h>
++#include <linux/in6.h>
++#include <linux/spinlock.h>
++#include <linux/highmem.h>
++#include <linux/smp_lock.h>
++#include <linux/ctype.h>
++#include <linux/uio.h>
++#include <asm/current.h>
++#include <asm/errno.h>
++#include <asm/kmap_types.h>
++#include <asm/semaphore.h>
++
++#include <ci/tools/config.h>
++
++#define ci_in_irq in_irq
++#define ci_in_interrupt in_interrupt
++#define ci_in_atomic in_atomic
++
++
++/**********************************************************************
++ * Misc stuff.
++ */
++
++#ifdef BUG
++# define CI_BOMB BUG
++#endif
++
++ci_inline void* __ci_alloc(size_t n)
++{ return kmalloc(n, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)); }
++
++ci_inline void* __ci_atomic_alloc(size_t n)
++{ return kmalloc(n, GFP_ATOMIC ); }
++
++ci_inline void __ci_free(void* p) { return kfree(p); }
++ci_inline void* __ci_vmalloc(size_t n) { return vmalloc(n); }
++ci_inline void __ci_vfree(void* p) { return vfree(p); }
++
++
++#if CI_MEMLEAK_DEBUG_ALLOC_TABLE
++ #define ci_alloc(s) ci_alloc_memleak_debug (s, __FILE__, __LINE__)
++ #define ci_atomic_alloc(s) ci_atomic_alloc_memleak_debug(s, __FILE__, __LINE__)
++ #define ci_free ci_free_memleak_debug
++ #define ci_vmalloc(s) ci_vmalloc_memleak_debug (s, __FILE__,__LINE__)
++ #define ci_vfree ci_vfree_memleak_debug
++ #define ci_alloc_fn ci_alloc_fn_memleak_debug
++ #define ci_vmalloc_fn ci_vmalloc_fn_memleak_debug
++#else /* !CI_MEMLEAK_DEBUG_ALLOC_TABLE */
++ #define ci_alloc_fn __ci_alloc
++ #define ci_vmalloc_fn __ci_vmalloc
++#endif
++
++#ifndef ci_alloc
++ #define ci_atomic_alloc __ci_atomic_alloc
++ #define ci_alloc __ci_alloc
++ #define ci_free __ci_free
++ #define ci_vmalloc __ci_vmalloc
++ #define ci_vmalloc_fn __ci_vmalloc
++ #define ci_vfree __ci_vfree
++#endif
++
++#define ci_sprintf sprintf
++#define ci_vsprintf vsprintf
++#define ci_snprintf snprintf
++#define ci_vsnprintf vsnprintf
++#define ci_sscanf sscanf
++
++
++#define CI_LOG_FN_DEFAULT ci_log_syslog
++
++
++/*--------------------------------------------------------------------
++ *
++ * irqs_disabled - needed for kmap helpers on some kernels
++ *
++ *--------------------------------------------------------------------*/
++#ifdef irqs_disabled
++# define ci_irqs_disabled irqs_disabled
++#else
++# if defined(__i386__) | defined(__x86_64__)
++# define ci_irqs_disabled(x) \
++ ({ \
++ unsigned long flags; \
++ local_save_flags(flags); \
++ !(flags & (1<<9)); \
++ })
++# else
++# error "Need to implement irqs_disabled() for your architecture"
++# endif
++#endif
++
++
++/**********************************************************************
++ * kmap helpers.
++ *
++ * Use ci_k(un)map for code paths which are not in an atomic context.
++ * For atomic code you need to use ci_k(un)map_in_atomic. This will grab
++ * one of the per-CPU kmap slots.
++ *
++ * NB in_interrupt != in_irq. If you don't know the difference then
++ * don't use kmap_in_atomic
++ *
++ * 2.4 allocates kmap slots by function. We are going to re-use the
++ * skb module's slot - we also use the same interlock
++ *
++ * 2.6 allocates kmap slots by type as well as by function. We are
++ * going to use the currently (2.6.10) unsused SOFTIRQ slot
++ *
++ */
++
++ci_inline void* ci_kmap(struct page *page) {
++ CI_DEBUG(if( ci_in_atomic() | ci_in_interrupt() | ci_in_irq() ) BUG());
++ return kmap(page);
++}
++
++ci_inline void ci_kunmap(struct page *page) {
++ kunmap(page);
++}
++
++#define CI_KM_SLOT KM_SOFTIRQ0
++
++
++typedef struct semaphore ci_semaphore_t;
++
++ci_inline void
++ci_sem_init (ci_semaphore_t *sem, int val) {
++ sema_init (sem, val);
++}
++
++ci_inline void
++ci_sem_down (ci_semaphore_t *sem) {
++ down (sem);
++}
++
++ci_inline int
++ci_sem_trydown (ci_semaphore_t *sem) {
++ return down_trylock (sem);
++}
++
++ci_inline void
++ci_sem_up (ci_semaphore_t *sem) {
++ up (sem);
++}
++
++ci_inline int
++ci_sem_get_count(ci_semaphore_t *sem) {
++ return sem->count.counter;
++}
++
++ci_inline void* ci_kmap_in_atomic(struct page *page)
++{
++ CI_DEBUG(if( ci_in_irq() ) BUG());
++
++ /* iSCSI can call without in_interrupt() but with irqs_disabled()
++ and in a context that can't sleep, so we need to check that
++ too */
++ if(ci_in_interrupt() || ci_irqs_disabled())
++ return kmap_atomic(page, CI_KM_SLOT);
++ else
++ return kmap(page);
++}
++
++ci_inline void ci_kunmap_in_atomic(struct page *page, void* kaddr)
++{
++ CI_DEBUG(if( ci_in_irq() ) BUG());
++
++ /* iSCSI can call without in_interrupt() but with irqs_disabled()
++ and in a context that can't sleep, so we need to check that
++ too */
++ if(ci_in_interrupt() || ci_irqs_disabled())
++ kunmap_atomic(kaddr, CI_KM_SLOT);
++ else
++ kunmap(page);
++}
++
++/**********************************************************************
++ * spinlock implementation: used by <ci/tools/spinlock.h>
++ */
++
++#define CI_HAVE_SPINLOCKS
++
++typedef ci_uintptr_t ci_lock_holder_t;
++#define ci_lock_thisthread (ci_lock_holder_t)current
++#define ci_lock_no_holder (ci_lock_holder_t)NULL
++
++typedef spinlock_t ci_lock_i;
++typedef spinlock_t ci_irqlock_i;
++typedef unsigned long ci_irqlock_state_t;
++
++#define IRQLOCK_CYCLES 500000
++
++#define ci_lock_ctor_i(l) spin_lock_init(l)
++#define ci_lock_dtor_i(l) do{}while(0)
++#define ci_lock_lock_i(l) spin_lock(l)
++#define ci_lock_trylock_i(l) spin_trylock(l)
++#define ci_lock_unlock_i(l) spin_unlock(l)
++
++#define ci_irqlock_ctor_i(l) spin_lock_init(l)
++#define ci_irqlock_dtor_i(l) do{}while(0)
++#define ci_irqlock_lock_i(l,s) spin_lock_irqsave(l,*(s))
++#define ci_irqlock_unlock_i(l,s) spin_unlock_irqrestore(l, *(s))
++
++
++/**********************************************************************
++ * register access
++ */
++
++#include <asm/io.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
++typedef volatile void __iomem* ioaddr_t;
++#else
++typedef unsigned long ioaddr_t;
++#endif
++
++
++
++/**********************************************************************
++ * thread implementation -- kernel dependancies probably should be
++ * moved to driver/linux_kernel.h
++ */
++
++#define ci_linux_daemonize(name) daemonize(name)
++
++#include <linux/workqueue.h>
++
++
++typedef struct {
++ void* (*fn)(void* arg);
++ void* arg;
++ const char* name;
++ int thrd_id;
++ struct completion exit_event;
++ struct work_struct keventd_witem;
++} ci_kernel_thread_t;
++
++
++typedef ci_kernel_thread_t* cithread_t;
++
++
++extern int cithread_create(cithread_t* tid, void* (*fn)(void*), void* arg,
++ const char* name);
++extern int cithread_detach(cithread_t kt);
++extern int cithread_join(cithread_t kt);
++
++
++/* Kernel sysctl variables. */
++extern int sysctl_tcp_wmem[3];
++extern int sysctl_tcp_rmem[3];
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
++#define LINUX_HAS_SYSCTL_MEM_MAX
++extern ci_uint32 sysctl_wmem_max;
++extern ci_uint32 sysctl_rmem_max;
++#endif
++
++
++/*--------------------------------------------------------------------
++ *
++ * ci_bigbuf_t: An abstraction of a large buffer. Needed because in the
++ * Linux kernel, large buffers need to be allocated with vmalloc(), whereas
++ * smaller buffers should use kmalloc(). This abstraction chooses the
++ * appropriate mechansim.
++ *
++ *--------------------------------------------------------------------*/
++
++typedef struct {
++ char* p;
++ int is_vmalloc;
++} ci_bigbuf_t;
++
++
++ci_inline int ci_bigbuf_alloc(ci_bigbuf_t* bb, size_t bytes) {
++ if( bytes >= CI_PAGE_SIZE && ! ci_in_atomic() ) {
++ bb->is_vmalloc = 1;
++ if( (bb->p = vmalloc(bytes)) ) return 0;
++ }
++ bb->is_vmalloc = 0;
++ bb->p = kmalloc(bytes, ci_in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
++ return bb->p ? 0 : -ENOMEM;
++}
++
++ci_inline void ci_bigbuf_free(ci_bigbuf_t* bb) {
++ if( bb->is_vmalloc ) vfree(bb->p);
++ else kfree(bb->p);
++}
++
++ci_inline char* ci_bigbuf_ptr(ci_bigbuf_t* bb)
++{ return bb->p; }
++
++/**********************************************************************
++ * struct iovec abstraction (for Windows port)
++ */
++
++typedef struct iovec ci_iovec;
++
++/* Accessors for buffer/length */
++#define CI_IOVEC_BASE(i) ((i)->iov_base)
++#define CI_IOVEC_LEN(i) ((i)->iov_len)
++
++/**********************************************************************
++ * Signals
++ */
++
++ci_inline void
++ci_send_sig(int signum)
++{
++ send_sig(signum, current, 0);
++}
++
++#endif /* __CI_TOOLS_LINUX_KERNEL_H__ */
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/sysdep.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/sysdep.h
+--- linux-2.6.18.8/drivers/xen/sfc_netback/ci/tools/sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/ci/tools/sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,132 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*! \cidoxg_include_ci_tools */
++
++#ifndef __CI_TOOLS_SYSDEP_H__
++#define __CI_TOOLS_SYSDEP_H__
++
++/* Make this header self-sufficient */
++#include <ci/compat.h>
++#include <ci/tools/log.h>
++#include <ci/tools/debug.h>
++
++
++/**********************************************************************
++ * Platform dependencies.
++ */
++
++#if defined(__KERNEL__)
++
++# if defined(__linux__)
++# include <ci/tools/platform/linux_kernel.h>
++# elif defined(_WIN32)
++# include <ci/tools/platform/win32_kernel.h>
++# elif defined(__sun__)
++# include <ci/tools/platform/sunos_kernel.h>
++# else
++# error Unknown platform.
++# endif
++
++#elif defined(_WIN32)
++
++# include <ci/tools/platform/win32.h>
++
++#elif defined(__unix__)
++
++# include <ci/tools/platform/unix.h>
++
++#else
++
++# error Unknown platform.
++
++#endif
++
++#if defined(__linux__)
++/*! Linux sendfile() support enable/disable. */
++# define CI_HAVE_SENDFILE /* provide sendfile i/f */
++
++# define CI_HAVE_OS_NOPAGE
++#endif
++
++#if defined(__sun__)
++# define CI_HAVE_SENDFILE /* provide sendfile i/f */
++# define CI_HAVE_SENDFILEV /* provide sendfilev i/f */
++
++# define CI_IOCTL_SENDFILE /* use efrm CI_SENDFILEV ioctl */
++#endif
++
++#if defined(_WIN32)
++typedef ci_uint32 ci_uerr_t; /* range of OS user-mode return codes */
++typedef ci_uint32 ci_kerr_t; /* range of OS kernel-mode return codes */
++#elif defined(__unix__)
++typedef ci_int32 ci_uerr_t; /* range of OS user-mode return codes */
++typedef ci_int32 ci_kerr_t; /* range of OS kernel-mode return codes */
++#endif
++
++
++/**********************************************************************
++ * Compiler and processor dependencies.
++ */
++
++#if defined(__GNUC__)
++
++#if defined(__i386__) || defined(__x86_64__)
++# include <ci/tools/platform/gcc_x86.h>
++#elif defined(__PPC__)
++# include <ci/tools/platform/gcc_ppc.h>
++#elif defined(__ia64__)
++# include <ci/tools/platform/gcc_ia64.h>
++#else
++# error Unknown processor.
++#endif
++
++#elif defined(_MSC_VER)
++
++#if defined(__i386__)
++# include <ci/tools/platform/msvc_x86.h>
++# elif defined(__x86_64__)
++# include <ci/tools/platform/msvc_x86_64.h>
++#else
++# error Unknown processor.
++#endif
++
++#elif defined(__PGI)
++
++# include <ci/tools/platform/pg_x86.h>
++
++#elif defined(__INTEL_COMPILER)
++
++/* Intel compilers v7 claim to be very gcc compatible. */
++# include <ci/tools/platform/gcc_x86.h>
++
++#else
++# error Unknown compiler.
++#endif
++
++
++#endif /* __CI_TOOLS_SYSDEP_H__ */
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netback/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/Makefile
+--- linux-2.6.18.8/drivers/xen/sfc_netback/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netback/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,12 @@
++EXTRA_CFLAGS += -Idrivers/xen/sfc_netback -Idrivers/xen/sfc_netutil -Idrivers/xen/netback -Idrivers/net/sfc
++EXTRA_CFLAGS += -D__ci_driver__
++EXTRA_CFLAGS += -DEFX_USE_KCOMPAT
++EXTRA_CFLAGS += -Werror
++
++ifdef GCOV
++EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage -DEFX_GCOV
++endif
++
++obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND) := sfc_netback.o
++
++sfc_netback-objs := accel.o accel_fwd.o accel_msg.o accel_solarflare.o accel_xenbus.o accel_debugfs.o
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_bufs.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_bufs.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_bufs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_bufs.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,393 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <xen/gnttab.h>
++
++#include "accel_bufs.h"
++#include "accel_util.h"
++
++#include "accel.h"
++
++
++static int
++netfront_accel_alloc_buf_desc_blocks(struct netfront_accel_bufinfo *manager,
++ int pages)
++{
++ manager->desc_blocks =
++ kzalloc(sizeof(struct netfront_accel_pkt_desc *) *
++ NETFRONT_ACCEL_BUF_NUM_BLOCKS(pages), GFP_KERNEL);
++ if (manager->desc_blocks == NULL) {
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++static int
++netfront_accel_alloc_buf_lists(struct netfront_accel_bufpages *bufpages,
++ int pages)
++{
++ bufpages->page_list = kmalloc(pages * sizeof(void *), GFP_KERNEL);
++ if (bufpages->page_list == NULL) {
++ return -ENOMEM;
++ }
++
++ bufpages->grant_list = kzalloc(pages * sizeof(grant_ref_t), GFP_KERNEL);
++ if (bufpages->grant_list == NULL) {
++ kfree(bufpages->page_list);
++ bufpages->page_list = NULL;
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++
++int netfront_accel_alloc_buffer_mem(struct netfront_accel_bufpages *bufpages,
++ struct netfront_accel_bufinfo *rx_manager,
++ struct netfront_accel_bufinfo *tx_manager,
++ int pages)
++{
++ int n, rc;
++
++ if ((rc = netfront_accel_alloc_buf_desc_blocks
++ (rx_manager, pages - (pages / sfc_netfront_buffer_split))) < 0) {
++ goto rx_fail;
++ }
++
++ if ((rc = netfront_accel_alloc_buf_desc_blocks
++ (tx_manager, pages / sfc_netfront_buffer_split)) < 0) {
++ goto tx_fail;
++ }
++
++ if ((rc = netfront_accel_alloc_buf_lists(bufpages, pages)) < 0) {
++ goto lists_fail;
++ }
++
++ for (n = 0; n < pages; n++) {
++ void *tmp = (void*)__get_free_page(GFP_KERNEL);
++ if (tmp == NULL)
++ break;
++
++ bufpages->page_list[n] = tmp;
++ }
++
++ if (n != pages) {
++ EPRINTK("%s: not enough pages: %d != %d\n", __FUNCTION__, n,
++ pages);
++ for (; n >= 0; n--)
++ free_page((unsigned long)(bufpages->page_list[n]));
++ rc = -ENOMEM;
++ goto pages_fail;
++ }
++
++ bufpages->max_pages = pages;
++ bufpages->page_reqs = 0;
++
++ return 0;
++
++ pages_fail:
++ kfree(bufpages->page_list);
++ kfree(bufpages->grant_list);
++
++ bufpages->page_list = NULL;
++ bufpages->grant_list = NULL;
++ lists_fail:
++ kfree(tx_manager->desc_blocks);
++ tx_manager->desc_blocks = NULL;
++
++ tx_fail:
++ kfree(rx_manager->desc_blocks);
++ rx_manager->desc_blocks = NULL;
++ rx_fail:
++ return rc;
++}
++
++
++void netfront_accel_free_buffer_mem(struct netfront_accel_bufpages *bufpages,
++ struct netfront_accel_bufinfo *rx_manager,
++ struct netfront_accel_bufinfo *tx_manager)
++{
++ int i;
++
++ for (i = 0; i < bufpages->max_pages; i++) {
++ if (bufpages->grant_list[i] != 0)
++ net_accel_ungrant_page(bufpages->grant_list[i]);
++ free_page((unsigned long)(bufpages->page_list[i]));
++ }
++
++ if (bufpages->max_pages) {
++ kfree(bufpages->page_list);
++ kfree(bufpages->grant_list);
++ kfree(rx_manager->desc_blocks);
++ kfree(tx_manager->desc_blocks);
++ }
++}
++
++
++/*
++ * Allocate memory for the buffer manager and create a lock. If no
++ * lock is supplied its own is allocated.
++ */
++struct netfront_accel_bufinfo *netfront_accel_init_bufs(spinlock_t *lock)
++{
++ struct netfront_accel_bufinfo *res = kmalloc(sizeof(*res), GFP_KERNEL);
++ if (res != NULL) {
++ res->npages = res->nused = 0;
++ res->first_free = -1;
++
++ if (lock == NULL) {
++ res->lock = kmalloc(sizeof(*res->lock), GFP_KERNEL);
++ if (res->lock == NULL) {
++ kfree(res);
++ return NULL;
++ }
++ spin_lock_init(res->lock);
++ res->internally_locked = 1;
++ } else {
++ res->lock = lock;
++ res->internally_locked = 0;
++ }
++
++ res->desc_blocks = NULL;
++ }
++
++ return res;
++}
++
++
++void netfront_accel_fini_bufs(struct netfront_accel_bufinfo *bufs)
++{
++ if (bufs->internally_locked)
++ kfree(bufs->lock);
++ kfree(bufs);
++}
++
++
++int netfront_accel_buf_map_request(struct xenbus_device *dev,
++ struct netfront_accel_bufpages *bufpages,
++ struct net_accel_msg *msg,
++ int pages, int offset)
++{
++ int i, mfn;
++ int err;
++
++ net_accel_msg_init(msg, NET_ACCEL_MSG_MAPBUF);
++
++ BUG_ON(pages > NET_ACCEL_MSG_MAX_PAGE_REQ);
++
++ msg->u.mapbufs.pages = pages;
++
++ for (i = 0; i < msg->u.mapbufs.pages; i++) {
++ /*
++ * This can happen if we tried to send this message
++ * earlier but the queue was full.
++ */
++ if (bufpages->grant_list[offset+i] != 0) {
++ msg->u.mapbufs.grants[i] =
++ bufpages->grant_list[offset+i];
++ continue;
++ }
++
++ mfn = virt_to_mfn(bufpages->page_list[offset+i]);
++ VPRINTK("%s: Granting page %d, mfn %08x\n",
++ __FUNCTION__, i, mfn);
++
++ bufpages->grant_list[offset+i] =
++ net_accel_grant_page(dev, mfn, 0);
++ msg->u.mapbufs.grants[i] = bufpages->grant_list[offset+i];
++
++ if (msg->u.mapbufs.grants[i] < 0) {
++ EPRINTK("%s: Failed to grant buffer: %d\n",
++ __FUNCTION__, msg->u.mapbufs.grants[i]);
++ err = -EIO;
++ goto error;
++ }
++ }
++
++ /* This is interpreted on return as the offset in the the page_list */
++ msg->u.mapbufs.reqid = offset;
++
++ return 0;
++
++error:
++ /* Ungrant all the pages we've successfully granted. */
++ for (i--; i >= 0; i--) {
++ net_accel_ungrant_page(bufpages->grant_list[offset+i]);
++ bufpages->grant_list[offset+i] = 0;
++ }
++ return err;
++}
++
++
++/* Process a response to a buffer request. */
++int netfront_accel_add_bufs(struct netfront_accel_bufpages *bufpages,
++ struct netfront_accel_bufinfo *manager,
++ struct net_accel_msg *msg)
++{
++ int msg_pages, page_offset, i, newtot;
++ int old_block_count, new_block_count;
++ u32 msg_buf;
++ unsigned long flags;
++
++ VPRINTK("%s: manager %p msg %p\n", __FUNCTION__, manager, msg);
++
++ BUG_ON(msg->id != (NET_ACCEL_MSG_MAPBUF | NET_ACCEL_MSG_REPLY));
++
++ msg_pages = msg->u.mapbufs.pages;
++ msg_buf = msg->u.mapbufs.buf;
++ page_offset = msg->u.mapbufs.reqid;
++
++ spin_lock_irqsave(manager->lock, flags);
++ newtot = manager->npages + msg_pages;
++ old_block_count =
++ (manager->npages + NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK - 1) >>
++ NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK_SHIFT;
++ new_block_count =
++ (newtot + NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK - 1) >>
++ NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK_SHIFT;
++
++ for (i = old_block_count; i < new_block_count; i++) {
++ struct netfront_accel_pkt_desc *block;
++ if (manager->desc_blocks[i] != NULL) {
++ VPRINTK("Not needed\n");
++ continue;
++ }
++ block = kzalloc(NETFRONT_ACCEL_BUFS_PER_BLOCK *
++ sizeof(netfront_accel_pkt_desc), GFP_ATOMIC);
++ if (block == NULL) {
++ spin_unlock_irqrestore(manager->lock, flags);
++ return -ENOMEM;
++ }
++ manager->desc_blocks[i] = block;
++ }
++ for (i = manager->npages; i < newtot; i++) {
++ int k, j = i - manager->npages;
++ int block_num;
++ int block_idx;
++ struct netfront_accel_pkt_desc *pkt;
++
++ block_num = i >> NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK_SHIFT;
++ block_idx = (NETFRONT_ACCEL_BUFS_PER_PAGE*i)
++ & (NETFRONT_ACCEL_BUFS_PER_BLOCK-1);
++
++ pkt = manager->desc_blocks[block_num] + block_idx;
++
++ for (k = 0; k < NETFRONT_ACCEL_BUFS_PER_PAGE; k++) {
++ BUG_ON(page_offset + j >= bufpages->max_pages);
++
++ pkt[k].buf_id = NETFRONT_ACCEL_BUFS_PER_PAGE * i + k;
++ pkt[k].pkt_kva = bufpages->page_list[page_offset + j] +
++ (PAGE_SIZE/NETFRONT_ACCEL_BUFS_PER_PAGE) * k;
++ pkt[k].pkt_buff_addr = msg_buf +
++ (PAGE_SIZE/NETFRONT_ACCEL_BUFS_PER_PAGE) *
++ (NETFRONT_ACCEL_BUFS_PER_PAGE * j + k);
++ pkt[k].next_free = manager->first_free;
++ manager->first_free = pkt[k].buf_id;
++ *(int*)(pkt[k].pkt_kva) = pkt[k].buf_id;
++
++ VPRINTK("buf %d desc %p kva %p buffaddr %x\n",
++ pkt[k].buf_id, &(pkt[k]), pkt[k].pkt_kva,
++ pkt[k].pkt_buff_addr);
++ }
++ }
++ manager->npages = newtot;
++ spin_unlock_irqrestore(manager->lock, flags);
++ VPRINTK("Added %d pages. Total is now %d\n", msg_pages,
++ manager->npages);
++ return 0;
++}
++
++
++netfront_accel_pkt_desc *
++netfront_accel_buf_find(struct netfront_accel_bufinfo *manager, u16 id)
++{
++ netfront_accel_pkt_desc *pkt;
++ int block_num = id >> NETFRONT_ACCEL_BUFS_PER_BLOCK_SHIFT;
++ int block_idx = id & (NETFRONT_ACCEL_BUFS_PER_BLOCK - 1);
++ BUG_ON(id >= manager->npages * NETFRONT_ACCEL_BUFS_PER_PAGE);
++ BUG_ON(block_idx >= NETFRONT_ACCEL_BUFS_PER_BLOCK);
++ pkt = manager->desc_blocks[block_num] + block_idx;
++ return pkt;
++}
++
++
++/* Allocate a buffer from the buffer manager */
++netfront_accel_pkt_desc *
++netfront_accel_buf_get(struct netfront_accel_bufinfo *manager)
++{
++ int bufno = -1;
++ netfront_accel_pkt_desc *buf = NULL;
++ unsigned long flags = 0;
++
++ /* Any spare? */
++ if (manager->first_free == -1)
++ return NULL;
++ /* Take lock */
++ if (manager->internally_locked)
++ spin_lock_irqsave(manager->lock, flags);
++ bufno = manager->first_free;
++ if (bufno != -1) {
++ buf = netfront_accel_buf_find(manager, bufno);
++ manager->first_free = buf->next_free;
++ manager->nused++;
++ }
++ /* Release lock */
++ if (manager->internally_locked)
++ spin_unlock_irqrestore(manager->lock, flags);
++
++ /* Tell the world */
++ VPRINTK("Allocated buffer %i, buffaddr %x\n", bufno,
++ buf->pkt_buff_addr);
++
++ return buf;
++}
++
++
++/* Release a buffer back to the buffer manager pool */
++int netfront_accel_buf_put(struct netfront_accel_bufinfo *manager, u16 id)
++{
++ netfront_accel_pkt_desc *buf = netfront_accel_buf_find(manager, id);
++ unsigned long flags = 0;
++ unsigned was_empty = 0;
++ int bufno = id;
++
++ VPRINTK("Freeing buffer %i\n", id);
++ BUG_ON(id == (u16)-1);
++
++ if (manager->internally_locked)
++ spin_lock_irqsave(manager->lock, flags);
++
++ if (manager->first_free == -1)
++ was_empty = 1;
++
++ buf->next_free = manager->first_free;
++ manager->first_free = bufno;
++ manager->nused--;
++
++ if (manager->internally_locked)
++ spin_unlock_irqrestore(manager->lock, flags);
++
++ return was_empty;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_bufs.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_bufs.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_bufs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_bufs.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,181 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NETFRONT_ACCEL_BUFS_H
++#define NETFRONT_ACCEL_BUFS_H
++
++#include <linux/skbuff.h>
++#include <linux/spinlock.h>
++#include <xen/xenbus.h>
++
++#include "accel_msg_iface.h"
++
++
++/*! Buffer descriptor structure */
++typedef struct netfront_accel_pkt_desc {
++ int buf_id;
++ u32 pkt_buff_addr;
++ void *pkt_kva;
++ /* This is the socket buffer currently married to this buffer */
++ struct sk_buff *skb;
++ int next_free;
++} netfront_accel_pkt_desc;
++
++
++#define NETFRONT_ACCEL_DEFAULT_BUF_PAGES (384)
++#define NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK_SHIFT (4)
++#define NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK \
++ (1 << (NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK_SHIFT))
++#define NETFRONT_ACCEL_BUFS_PER_PAGE_SHIFT (1)
++#define NETFRONT_ACCEL_BUFS_PER_PAGE \
++ (1 << (NETFRONT_ACCEL_BUFS_PER_PAGE_SHIFT))
++#define NETFRONT_ACCEL_BUFS_PER_BLOCK_SHIFT \
++ (NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK_SHIFT + \
++ NETFRONT_ACCEL_BUFS_PER_PAGE_SHIFT)
++#define NETFRONT_ACCEL_BUFS_PER_BLOCK \
++ (1 << NETFRONT_ACCEL_BUFS_PER_BLOCK_SHIFT)
++#define NETFRONT_ACCEL_BUF_NUM_BLOCKS(max_pages) \
++ (((max_pages)+NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK-1) / \
++ NETFRONT_ACCEL_BUF_PAGES_PER_BLOCK)
++
++/*! Buffer management structure. */
++struct netfront_accel_bufinfo {
++ /* number added to this manager */
++ unsigned npages;
++ /* number currently used from this manager */
++ unsigned nused;
++
++ int first_free;
++
++ int internally_locked;
++ spinlock_t *lock;
++
++ /*
++ * array of pointers (length NETFRONT_ACCEL_BUF_NUM_BLOCKS) to
++ * pkt descs
++ */
++ struct netfront_accel_pkt_desc **desc_blocks;
++};
++
++
++struct netfront_accel_bufpages {
++ /* length of lists of pages/grants */
++ int max_pages;
++ /* list of pages allocated for network buffers */
++ void **page_list;
++ /* list of grants for the above pages */
++ grant_ref_t *grant_list;
++
++ /* number of page requests that have been made */
++ unsigned page_reqs;
++};
++
++
++/*! Allocate memory for the buffer manager, set up locks etc.
++ * Optionally takes a lock to use, if not supplied it makes its own.
++ *
++ * \return pointer to netfront_accel_bufinfo structure that represents the
++ * buffer manager
++ */
++extern struct netfront_accel_bufinfo *
++netfront_accel_init_bufs(spinlock_t *lock);
++
++/*! Allocate memory for the buffers
++ */
++extern int
++netfront_accel_alloc_buffer_mem(struct netfront_accel_bufpages *bufpages,
++ struct netfront_accel_bufinfo *rx_res,
++ struct netfront_accel_bufinfo *tx_res,
++ int pages);
++extern void
++netfront_accel_free_buffer_mem(struct netfront_accel_bufpages *bufpages,
++ struct netfront_accel_bufinfo *rx_res,
++ struct netfront_accel_bufinfo *tx_res);
++
++/*! Release memory for the buffer manager, buffers, etc.
++ *
++ * \param manager pointer to netfront_accel_bufinfo structure that
++ * represents the buffer manager
++ */
++extern void netfront_accel_fini_bufs(struct netfront_accel_bufinfo *manager);
++
++/*! Release a buffer.
++ *
++ * \param manager The buffer manager which owns the buffer.
++ * \param id The buffer identifier.
++ */
++extern int netfront_accel_buf_put(struct netfront_accel_bufinfo *manager,
++ u16 id);
++
++/*! Get the packet descriptor associated with a buffer id.
++ *
++ * \param manager The buffer manager which owns the buffer.
++ * \param id The buffer identifier.
++ *
++ * The returned value is the packet descriptor for this buffer.
++ */
++extern netfront_accel_pkt_desc *
++netfront_accel_buf_find(struct netfront_accel_bufinfo *manager, u16 id);
++
++
++/*! Fill out a message request for some buffers to be mapped by the
++ * back end driver
++ *
++ * \param manager The buffer manager
++ * \param msg Pointer to an ef_msg to complete.
++ * \return 0 on success
++ */
++extern int
++netfront_accel_buf_map_request(struct xenbus_device *dev,
++ struct netfront_accel_bufpages *bufpages,
++ struct net_accel_msg *msg,
++ int pages, int offset);
++
++/*! Process a response to a buffer request.
++ *
++ * Deal with a received message from the back end in response to our
++ * request for buffers
++ *
++ * \param manager The buffer manager
++ * \param msg The received message from the back end describing new
++ * buffers
++ * \return 0 on success
++ */
++extern int
++netfront_accel_add_bufs(struct netfront_accel_bufpages *bufpages,
++ struct netfront_accel_bufinfo *manager,
++ struct net_accel_msg *msg);
++
++
++/*! Allocate a buffer from the buffer manager
++ *
++ * \param manager The buffer manager data structure
++ * \param id On exit, the id of the buffer allocated
++ * \return Pointer to buffer descriptor.
++ */
++struct netfront_accel_pkt_desc *
++netfront_accel_buf_get(struct netfront_accel_bufinfo *manager);
++
++#endif /* NETFRONT_ACCEL_BUFS_H */
++
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_debugfs.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_debugfs.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_debugfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_debugfs.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,211 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/fs.h>
++#include <linux/debugfs.h>
++
++#include "accel.h"
++
++#if defined(CONFIG_DEBUG_FS)
++static struct dentry *sfc_debugfs_root = NULL;
++#endif
++
++void netfront_accel_debugfs_init(void)
++{
++#if defined(CONFIG_DEBUG_FS)
++ sfc_debugfs_root = debugfs_create_dir(frontend_name, NULL);
++#endif
++}
++
++
++void netfront_accel_debugfs_fini(void)
++{
++#if defined(CONFIG_DEBUG_FS)
++ if (sfc_debugfs_root)
++ debugfs_remove(sfc_debugfs_root);
++#endif
++}
++
++
++int netfront_accel_debugfs_create(netfront_accel_vnic *vnic)
++{
++#if defined(CONFIG_DEBUG_FS)
++ if (sfc_debugfs_root == NULL)
++ return -ENOENT;
++
++ vnic->dbfs_dir = debugfs_create_dir(vnic->net_dev->name,
++ sfc_debugfs_root);
++ if (vnic->dbfs_dir == NULL)
++ return -ENOMEM;
++
++ vnic->netdev_dbfs.fastpath_rx_pkts = debugfs_create_u32
++ ("fastpath_rx_pkts", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->netdev_stats.fastpath_rx_pkts);
++ vnic->netdev_dbfs.fastpath_rx_bytes = debugfs_create_u32
++ ("fastpath_rx_bytes", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->netdev_stats.fastpath_rx_bytes);
++ vnic->netdev_dbfs.fastpath_rx_errors = debugfs_create_u32
++ ("fastpath_rx_errors", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->netdev_stats.fastpath_rx_errors);
++ vnic->netdev_dbfs.fastpath_tx_pkts = debugfs_create_u32
++ ("fastpath_tx_pkts", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->netdev_stats.fastpath_tx_pkts);
++ vnic->netdev_dbfs.fastpath_tx_bytes = debugfs_create_u32
++ ("fastpath_tx_bytes", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->netdev_stats.fastpath_tx_bytes);
++ vnic->netdev_dbfs.fastpath_tx_errors = debugfs_create_u32
++ ("fastpath_tx_errors", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->netdev_stats.fastpath_tx_errors);
++
++#if NETFRONT_ACCEL_STATS
++ vnic->dbfs.irq_count = debugfs_create_u64
++ ("irq_count", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.irq_count);
++ vnic->dbfs.useless_irq_count = debugfs_create_u64
++ ("useless_irq_count", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.useless_irq_count);
++ vnic->dbfs.poll_schedule_count = debugfs_create_u64
++ ("poll_schedule_count", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.poll_schedule_count);
++ vnic->dbfs.poll_call_count = debugfs_create_u64
++ ("poll_call_count", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.poll_call_count);
++ vnic->dbfs.poll_reschedule_count = debugfs_create_u64
++ ("poll_reschedule_count", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.poll_reschedule_count);
++ vnic->dbfs.queue_stops = debugfs_create_u64
++ ("queue_stops", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.queue_stops);
++ vnic->dbfs.queue_wakes = debugfs_create_u64
++ ("queue_wakes", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.queue_wakes);
++ vnic->dbfs.ssr_bursts = debugfs_create_u64
++ ("ssr_bursts", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.ssr_bursts);
++ vnic->dbfs.ssr_drop_stream = debugfs_create_u64
++ ("ssr_drop_stream", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.ssr_drop_stream);
++ vnic->dbfs.ssr_misorder = debugfs_create_u64
++ ("ssr_misorder", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.ssr_misorder);
++ vnic->dbfs.ssr_slow_start = debugfs_create_u64
++ ("ssr_slow_start", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.ssr_slow_start);
++ vnic->dbfs.ssr_merges = debugfs_create_u64
++ ("ssr_merges", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.ssr_merges);
++ vnic->dbfs.ssr_too_many = debugfs_create_u64
++ ("ssr_too_many", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.ssr_too_many);
++ vnic->dbfs.ssr_new_stream = debugfs_create_u64
++ ("ssr_new_stream", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.ssr_new_stream);
++
++ vnic->dbfs.fastpath_tx_busy = debugfs_create_u64
++ ("fastpath_tx_busy", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.fastpath_tx_busy);
++ vnic->dbfs.fastpath_tx_completions = debugfs_create_u64
++ ("fastpath_tx_completions", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.fastpath_tx_completions);
++ vnic->dbfs.fastpath_tx_pending_max = debugfs_create_u32
++ ("fastpath_tx_pending_max", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.fastpath_tx_pending_max);
++ vnic->dbfs.event_count = debugfs_create_u64
++ ("event_count", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.event_count);
++ vnic->dbfs.bad_event_count = debugfs_create_u64
++ ("bad_event_count", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.bad_event_count);
++ vnic->dbfs.event_count_since_irq = debugfs_create_u32
++ ("event_count_since_irq", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.event_count_since_irq);
++ vnic->dbfs.events_per_irq_max = debugfs_create_u32
++ ("events_per_irq_max", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.events_per_irq_max);
++ vnic->dbfs.fastpath_frm_trunc = debugfs_create_u64
++ ("fastpath_frm_trunc", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.fastpath_frm_trunc);
++ vnic->dbfs.rx_no_desc_trunc = debugfs_create_u64
++ ("rx_no_desc_trunc", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.rx_no_desc_trunc);
++ vnic->dbfs.events_per_poll_max = debugfs_create_u32
++ ("events_per_poll_max", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.events_per_poll_max);
++ vnic->dbfs.events_per_poll_rx_max = debugfs_create_u32
++ ("events_per_poll_rx_max", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.events_per_poll_rx_max);
++ vnic->dbfs.events_per_poll_tx_max = debugfs_create_u32
++ ("events_per_poll_tx_max", S_IRUSR | S_IRGRP | S_IROTH,
++ vnic->dbfs_dir, &vnic->stats.events_per_poll_tx_max);
++#endif
++#endif
++ return 0;
++}
++
++
++int netfront_accel_debugfs_remove(netfront_accel_vnic *vnic)
++{
++#if defined(CONFIG_DEBUG_FS)
++ if (vnic->dbfs_dir != NULL) {
++ debugfs_remove(vnic->netdev_dbfs.fastpath_rx_pkts);
++ debugfs_remove(vnic->netdev_dbfs.fastpath_rx_bytes);
++ debugfs_remove(vnic->netdev_dbfs.fastpath_rx_errors);
++ debugfs_remove(vnic->netdev_dbfs.fastpath_tx_pkts);
++ debugfs_remove(vnic->netdev_dbfs.fastpath_tx_bytes);
++ debugfs_remove(vnic->netdev_dbfs.fastpath_tx_errors);
++
++#if NETFRONT_ACCEL_STATS
++ debugfs_remove(vnic->dbfs.irq_count);
++ debugfs_remove(vnic->dbfs.useless_irq_count);
++ debugfs_remove(vnic->dbfs.poll_schedule_count);
++ debugfs_remove(vnic->dbfs.poll_call_count);
++ debugfs_remove(vnic->dbfs.poll_reschedule_count);
++ debugfs_remove(vnic->dbfs.queue_stops);
++ debugfs_remove(vnic->dbfs.queue_wakes);
++ debugfs_remove(vnic->dbfs.ssr_bursts);
++ debugfs_remove(vnic->dbfs.ssr_drop_stream);
++ debugfs_remove(vnic->dbfs.ssr_misorder);
++ debugfs_remove(vnic->dbfs.ssr_slow_start);
++ debugfs_remove(vnic->dbfs.ssr_merges);
++ debugfs_remove(vnic->dbfs.ssr_too_many);
++ debugfs_remove(vnic->dbfs.ssr_new_stream);
++
++ debugfs_remove(vnic->dbfs.fastpath_tx_busy);
++ debugfs_remove(vnic->dbfs.fastpath_tx_completions);
++ debugfs_remove(vnic->dbfs.fastpath_tx_pending_max);
++ debugfs_remove(vnic->dbfs.event_count);
++ debugfs_remove(vnic->dbfs.bad_event_count);
++ debugfs_remove(vnic->dbfs.event_count_since_irq);
++ debugfs_remove(vnic->dbfs.events_per_irq_max);
++ debugfs_remove(vnic->dbfs.fastpath_frm_trunc);
++ debugfs_remove(vnic->dbfs.rx_no_desc_trunc);
++ debugfs_remove(vnic->dbfs.events_per_poll_max);
++ debugfs_remove(vnic->dbfs.events_per_poll_rx_max);
++ debugfs_remove(vnic->dbfs.events_per_poll_tx_max);
++#endif
++ debugfs_remove(vnic->dbfs_dir);
++ }
++#endif
++ return 0;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,477 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NETFRONT_ACCEL_H
++#define NETFRONT_ACCEL_H
++
++#include "accel_msg_iface.h"
++#include "accel_cuckoo_hash.h"
++#include "accel_bufs.h"
++
++#include "etherfabric/ef_vi.h"
++
++#include <xen/xenbus.h>
++#include <xen/evtchn.h>
++
++#include <linux/kernel.h>
++#include <linux/list.h>
++
++enum netfront_accel_post_status {
++ NETFRONT_ACCEL_STATUS_GOOD,
++ NETFRONT_ACCEL_STATUS_BUSY,
++ NETFRONT_ACCEL_STATUS_CANT
++};
++
++#define NETFRONT_ACCEL_STATS 1
++#if NETFRONT_ACCEL_STATS
++#define NETFRONT_ACCEL_STATS_OP(x) x
++#else
++#define NETFRONT_ACCEL_STATS_OP(x)
++#endif
++
++
++enum netfront_accel_msg_state {
++ NETFRONT_ACCEL_MSG_NONE = 0,
++ NETFRONT_ACCEL_MSG_HELLO = 1,
++ NETFRONT_ACCEL_MSG_HW = 2
++};
++
++
++typedef struct {
++ u32 in_progress;
++ u32 total_len;
++ struct sk_buff *skb;
++} netfront_accel_jumbo_state;
++
++
++struct netfront_accel_ssr_state {
++ /** List of tracked connections. */
++ struct list_head conns;
++
++ /** Free efx_ssr_conn instances. */
++ struct list_head free_conns;
++};
++
++
++struct netfront_accel_netdev_stats {
++ /* Fastpath stats. */
++ u32 fastpath_rx_pkts;
++ u32 fastpath_rx_bytes;
++ u32 fastpath_rx_errors;
++ u32 fastpath_tx_pkts;
++ u32 fastpath_tx_bytes;
++ u32 fastpath_tx_errors;
++};
++
++
++struct netfront_accel_netdev_dbfs {
++ struct dentry *fastpath_rx_pkts;
++ struct dentry *fastpath_rx_bytes;
++ struct dentry *fastpath_rx_errors;
++ struct dentry *fastpath_tx_pkts;
++ struct dentry *fastpath_tx_bytes;
++ struct dentry *fastpath_tx_errors;
++};
++
++
++struct netfront_accel_stats {
++ /** Fast path events */
++ u64 fastpath_tx_busy;
++
++ /** TX DMA queue status */
++ u64 fastpath_tx_completions;
++
++ /** The number of events processed. */
++ u64 event_count;
++
++ /** Number of frame trunc events seen on fastpath */
++ u64 fastpath_frm_trunc;
++
++ /** Number of no rx descriptor trunc events seen on fastpath */
++ u64 rx_no_desc_trunc;
++
++ /** The number of misc bad events (e.g. RX_DISCARD) processed. */
++ u64 bad_event_count;
++
++ /** Number of events dealt with in poll loop */
++ u32 events_per_poll_max;
++ u32 events_per_poll_tx_max;
++ u32 events_per_poll_rx_max;
++
++ /** Largest number of concurrently outstanding tx descriptors */
++ u32 fastpath_tx_pending_max;
++
++ /** The number of events since the last interrupts. */
++ u32 event_count_since_irq;
++
++ /** The max number of events between interrupts. */
++ u32 events_per_irq_max;
++
++ /** The number of interrupts. */
++ u64 irq_count;
++
++ /** The number of useless interrupts. */
++ u64 useless_irq_count;
++
++ /** The number of polls scheduled. */
++ u64 poll_schedule_count;
++
++ /** The number of polls called. */
++ u64 poll_call_count;
++
++ /** The number of rechecks. */
++ u64 poll_reschedule_count;
++
++ /** Number of times we've called netif_stop_queue/netif_wake_queue */
++ u64 queue_stops;
++ u64 queue_wakes;
++
++ /** SSR stats */
++ u64 ssr_bursts;
++ u64 ssr_drop_stream;
++ u64 ssr_misorder;
++ u64 ssr_slow_start;
++ u64 ssr_merges;
++ u64 ssr_too_many;
++ u64 ssr_new_stream;
++};
++
++
++struct netfront_accel_dbfs {
++ struct dentry *fastpath_tx_busy;
++ struct dentry *fastpath_tx_completions;
++ struct dentry *fastpath_tx_pending_max;
++ struct dentry *fastpath_frm_trunc;
++ struct dentry *rx_no_desc_trunc;
++ struct dentry *event_count;
++ struct dentry *bad_event_count;
++ struct dentry *events_per_poll_max;
++ struct dentry *events_per_poll_rx_max;
++ struct dentry *events_per_poll_tx_max;
++ struct dentry *event_count_since_irq;
++ struct dentry *events_per_irq_max;
++ struct dentry *irq_count;
++ struct dentry *useless_irq_count;
++ struct dentry *poll_schedule_count;
++ struct dentry *poll_call_count;
++ struct dentry *poll_reschedule_count;
++ struct dentry *queue_stops;
++ struct dentry *queue_wakes;
++ struct dentry *ssr_bursts;
++ struct dentry *ssr_drop_stream;
++ struct dentry *ssr_misorder;
++ struct dentry *ssr_slow_start;
++ struct dentry *ssr_merges;
++ struct dentry *ssr_too_many;
++ struct dentry *ssr_new_stream;
++};
++
++
++typedef struct netfront_accel_vnic {
++ struct netfront_accel_vnic *next;
++
++ struct mutex vnic_mutex;
++
++ spinlock_t tx_lock;
++
++ struct netfront_accel_bufpages bufpages;
++ struct netfront_accel_bufinfo *rx_bufs;
++ struct netfront_accel_bufinfo *tx_bufs;
++
++ /** Hardware & VI state */
++ ef_vi vi;
++
++ ef_vi_state *vi_state;
++
++ ef_eventq_state evq_state;
++
++ void *evq_mapping;
++
++ /** Hardware dependant state */
++ union {
++ struct {
++ /** Falcon A or B */
++ enum net_accel_hw_type type;
++ u32 *evq_rptr;
++ u32 *doorbell;
++ void *evq_rptr_mapping;
++ void *doorbell_mapping;
++ void *txdmaq_mapping;
++ void *rxdmaq_mapping;
++ } falcon;
++ } hw;
++
++ /** RX DMA queue status */
++ u32 rx_dma_level;
++
++ /** Number of RX descriptors waiting to be pushed to the card. */
++ u32 rx_dma_batched;
++#define NETFRONT_ACCEL_RX_DESC_BATCH 16
++
++ /**
++ * Hash table of remote mac addresses to decide whether to try
++ * fast path
++ */
++ cuckoo_hash_table fastpath_table;
++ spinlock_t table_lock;
++
++ /** the local mac address of virtual interface we're accelerating */
++ u8 mac[ETH_ALEN];
++
++ int rx_pkt_stride;
++ int rx_skb_stride;
++
++ /**
++ * Keep track of fragments of jumbo packets as events are
++ * delivered by NIC
++ */
++ netfront_accel_jumbo_state jumbo_state;
++
++ struct net_device *net_dev;
++
++ /** These two gate the enabling of fast path operations */
++ int frontend_ready;
++ int backend_netdev_up;
++
++ int irq_enabled;
++ spinlock_t irq_enabled_lock;
++
++ int tx_enabled;
++
++ int poll_enabled;
++
++ /** A spare slot for a TX packet. This is treated as an extension
++ * of the DMA queue. */
++ struct sk_buff *tx_skb;
++
++ /** Keep track of fragments of SSR packets */
++ struct netfront_accel_ssr_state ssr_state;
++
++ struct xenbus_device *dev;
++
++ /** Event channel for messages */
++ int msg_channel;
++ int msg_channel_irq;
++
++ /** Event channel for network interrupts. */
++ int net_channel;
++ int net_channel_irq;
++
++ struct net_accel_shared_page *shared_page;
++
++ grant_ref_t ctrl_page_gnt;
++ grant_ref_t msg_page_gnt;
++
++ /** Message Qs, 1 each way. */
++ sh_msg_fifo2 to_dom0;
++ sh_msg_fifo2 from_dom0;
++
++ enum netfront_accel_msg_state msg_state;
++
++ /** Watch on accelstate */
++ struct xenbus_watch backend_accel_watch;
++ /** Watch on frontend's MAC address */
++ struct xenbus_watch mac_address_watch;
++
++ /** Work to process received irq/msg */
++ struct work_struct msg_from_bend;
++
++ /** Wait queue for changes in accelstate. */
++ wait_queue_head_t state_wait_queue;
++
++ /** The current accelstate of this driver. */
++ XenbusState frontend_state;
++
++ /** The most recent accelstate seen by the xenbus watch. */
++ XenbusState backend_state;
++
++ /** Non-zero if we should reject requests to connect. */
++ int removing;
++
++ /** Non-zero if the domU shared state has been initialised. */
++ int domU_state_is_setup;
++
++ /** Non-zero if the dom0 shared state has been initialised. */
++ int dom0_state_is_setup;
++
++ /* Those statistics that are added to the netdev stats */
++ struct netfront_accel_netdev_stats netdev_stats;
++ struct netfront_accel_netdev_stats stats_last_read;
++#ifdef CONFIG_DEBUG_FS
++ struct netfront_accel_netdev_dbfs netdev_dbfs;
++#endif
++
++ /* These statistics are internal and optional */
++#if NETFRONT_ACCEL_STATS
++ struct netfront_accel_stats stats;
++#ifdef CONFIG_DEBUG_FS
++ struct netfront_accel_dbfs dbfs;
++#endif
++#endif
++
++ /** Debufs fs dir for this interface */
++ struct dentry *dbfs_dir;
++} netfront_accel_vnic;
++
++
++/* Module parameters */
++extern unsigned sfc_netfront_max_pages;
++extern unsigned sfc_netfront_buffer_split;
++
++extern const char *frontend_name;
++extern struct netfront_accel_hooks accel_hooks;
++extern struct workqueue_struct *netfront_accel_workqueue;
++
++
++extern
++void netfront_accel_vi_ctor(netfront_accel_vnic *vnic);
++
++extern
++int netfront_accel_vi_init(netfront_accel_vnic *vnic,
++ struct net_accel_msg_hw *hw_msg);
++
++extern
++void netfront_accel_vi_dtor(netfront_accel_vnic *vnic);
++
++
++/**
++ * Add new buffers which have been registered with the NIC.
++ *
++ * @v vnic The vnic instance to process the response.
++ *
++ * The buffers contained in the message are added to the buffer pool.
++ */
++extern
++void netfront_accel_vi_add_bufs(netfront_accel_vnic *vnic, int is_rx);
++
++/**
++ * Put a packet on the tx DMA queue.
++ *
++ * @v vnic The vnic instance to accept the packet.
++ * @v skb A sk_buff to send.
++ *
++ * Attempt to send a packet. On success, the skb is owned by the DMA
++ * queue and will be released when the completion event arrives.
++ */
++extern enum netfront_accel_post_status
++netfront_accel_vi_tx_post(netfront_accel_vnic *vnic,
++ struct sk_buff *skb);
++
++
++/**
++ * Process events in response to an interrupt.
++ *
++ * @v vnic The vnic instance to poll.
++ * @v rx_packets The maximum number of rx packets to process.
++ * @ret rx_done The number of rx packets processed.
++ *
++ * The vnic will process events until there are no more events
++ * remaining or the specified number of rx packets has been processed.
++ * The split from the interrupt call is to allow Linux NAPI
++ * polling.
++ */
++extern
++int netfront_accel_vi_poll(netfront_accel_vnic *vnic, int rx_packets);
++
++
++/**
++ * Iterate over the fragments of a packet buffer.
++ *
++ * @v skb The packet buffer to examine.
++ * @v idx A variable name for the fragment index.
++ * @v data A variable name for the address of the fragment data.
++ * @v length A variable name for the fragment length.
++ * @v code A section of code to execute for each fragment.
++ *
++ * This macro iterates over the fragments in a packet buffer and
++ * executes the code for each of them.
++ */
++#define NETFRONT_ACCEL_PKTBUFF_FOR_EACH_FRAGMENT(skb, frag_idx, \
++ frag_data, frag_len, \
++ code) \
++ do { \
++ int frag_idx; \
++ void *frag_data; \
++ unsigned int frag_len; \
++ \
++ frag_data = skb->data; \
++ frag_len = skb_headlen(skb); \
++ frag_idx = 0; \
++ while (1) { /* For each fragment */ \
++ code; \
++ if (frag_idx >= skb_shinfo(skb)->nr_frags) { \
++ break; \
++ } else { \
++ skb_frag_t *fragment; \
++ fragment = &skb_shinfo(skb)->frags[frag_idx]; \
++ frag_len = fragment->size; \
++ frag_data = ((void*)page_address(fragment->page) \
++ + fragment->page_offset); \
++ }; \
++ frag_idx++; \
++ } \
++ } while(0)
++
++static inline
++void netfront_accel_disable_net_interrupts(netfront_accel_vnic *vnic)
++{
++ mask_evtchn(vnic->net_channel);
++}
++
++static inline
++void netfront_accel_enable_net_interrupts(netfront_accel_vnic *vnic)
++{
++ unmask_evtchn(vnic->net_channel);
++}
++
++void netfront_accel_msg_tx_fastpath(netfront_accel_vnic *vnic, const void *mac,
++ u32 ip, u16 port, u8 protocol);
++
++/* Process an IRQ received from back end driver */
++irqreturn_t netfront_accel_msg_channel_irq_from_bend(int irq, void *context,
++ struct pt_regs *unused);
++irqreturn_t netfront_accel_net_channel_irq_from_bend(int irq, void *context,
++ struct pt_regs *unused);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++extern void netfront_accel_msg_from_bend(struct work_struct *context);
++#else
++extern void netfront_accel_msg_from_bend(void *context);
++#endif
++
++extern void vnic_stop_fastpath(netfront_accel_vnic *vnic);
++
++extern int netfront_accel_probe(struct net_device *net_dev,
++ struct xenbus_device *dev);
++extern int netfront_accel_remove(struct xenbus_device *dev);
++extern void netfront_accel_set_closing(netfront_accel_vnic *vnic);
++
++extern int netfront_accel_vi_enable_interrupts(netfront_accel_vnic *vnic);
++
++extern void netfront_accel_debugfs_init(void);
++extern void netfront_accel_debugfs_fini(void);
++extern int netfront_accel_debugfs_create(netfront_accel_vnic *vnic);
++extern int netfront_accel_debugfs_remove(netfront_accel_vnic *vnic);
++
++#endif /* NETFRONT_ACCEL_H */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_msg.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_msg.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_msg.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_msg.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,566 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/stddef.h>
++#include <linux/errno.h>
++
++#include <xen/xenbus.h>
++
++#include "accel.h"
++#include "accel_msg_iface.h"
++#include "accel_util.h"
++#include "accel_bufs.h"
++
++#include "netfront.h" /* drivers/xen/netfront/netfront.h */
++
++static void vnic_start_interrupts(netfront_accel_vnic *vnic)
++{
++ unsigned long flags;
++
++ /* Prime our interrupt */
++ spin_lock_irqsave(&vnic->irq_enabled_lock, flags);
++ if (!netfront_accel_vi_enable_interrupts(vnic)) {
++ /* Cripes, that was quick, better pass it up */
++ netfront_accel_disable_net_interrupts(vnic);
++ vnic->irq_enabled = 0;
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.poll_schedule_count++);
++ netif_rx_schedule(vnic->net_dev);
++ } else {
++ /*
++ * Nothing yet, make sure we get interrupts through
++ * back end
++ */
++ vnic->irq_enabled = 1;
++ netfront_accel_enable_net_interrupts(vnic);
++ }
++ spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
++}
++
++
++static void vnic_stop_interrupts(netfront_accel_vnic *vnic)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&vnic->irq_enabled_lock, flags);
++ netfront_accel_disable_net_interrupts(vnic);
++ vnic->irq_enabled = 0;
++ spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
++}
++
++
++static void vnic_start_fastpath(netfront_accel_vnic *vnic)
++{
++ struct net_device *net_dev = vnic->net_dev;
++ unsigned long flags;
++
++ DPRINTK("%s\n", __FUNCTION__);
++
++ spin_lock_irqsave(&vnic->tx_lock, flags);
++ vnic->tx_enabled = 1;
++ spin_unlock_irqrestore(&vnic->tx_lock, flags);
++
++ netif_poll_disable(net_dev);
++ vnic->poll_enabled = 1;
++ netif_poll_enable(net_dev);
++
++ vnic_start_interrupts(vnic);
++}
++
++
++void vnic_stop_fastpath(netfront_accel_vnic *vnic)
++{
++ struct net_device *net_dev = vnic->net_dev;
++ struct netfront_info *np = (struct netfront_info *)netdev_priv(net_dev);
++ unsigned long flags1, flags2;
++
++ DPRINTK("%s\n", __FUNCTION__);
++
++ vnic_stop_interrupts(vnic);
++
++ spin_lock_irqsave(&vnic->tx_lock, flags1);
++ vnic->tx_enabled = 0;
++ spin_lock_irqsave(&np->tx_lock, flags2);
++ if (vnic->tx_skb != NULL) {
++ dev_kfree_skb_any(vnic->tx_skb);
++ vnic->tx_skb = NULL;
++ if (netfront_check_queue_ready(net_dev)) {
++ netif_wake_queue(net_dev);
++ NETFRONT_ACCEL_STATS_OP
++ (vnic->stats.queue_wakes++);
++ }
++ }
++ spin_unlock_irqrestore(&np->tx_lock, flags2);
++ spin_unlock_irqrestore(&vnic->tx_lock, flags1);
++
++ /* Must prevent polls and hold lock to modify poll_enabled */
++ netif_poll_disable(net_dev);
++ spin_lock_irqsave(&vnic->irq_enabled_lock, flags1);
++ vnic->poll_enabled = 0;
++ spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags1);
++ netif_poll_enable(net_dev);
++}
++
++
++static void netfront_accel_interface_up(netfront_accel_vnic *vnic)
++{
++
++ if (!vnic->backend_netdev_up) {
++ vnic->backend_netdev_up = 1;
++
++ if (vnic->frontend_ready)
++ vnic_start_fastpath(vnic);
++ }
++}
++
++
++static void netfront_accel_interface_down(netfront_accel_vnic *vnic)
++{
++
++ if (vnic->backend_netdev_up) {
++ vnic->backend_netdev_up = 0;
++
++ if (vnic->frontend_ready)
++ vnic_stop_fastpath(vnic);
++ }
++}
++
++
++static int vnic_add_bufs(netfront_accel_vnic *vnic,
++ struct net_accel_msg *msg)
++{
++ int rc, offset;
++ struct netfront_accel_bufinfo *bufinfo;
++
++ BUG_ON(msg->u.mapbufs.pages > NET_ACCEL_MSG_MAX_PAGE_REQ);
++
++ offset = msg->u.mapbufs.reqid;
++
++ if (offset < vnic->bufpages.max_pages -
++ (vnic->bufpages.max_pages / sfc_netfront_buffer_split)) {
++ bufinfo = vnic->rx_bufs;
++ } else
++ bufinfo = vnic->tx_bufs;
++
++ /* Queue up some Rx buffers to start things off. */
++ if ((rc = netfront_accel_add_bufs(&vnic->bufpages, bufinfo, msg)) == 0) {
++ netfront_accel_vi_add_bufs(vnic, bufinfo == vnic->rx_bufs);
++
++ if (offset + msg->u.mapbufs.pages == vnic->bufpages.max_pages) {
++ VPRINTK("%s: got all buffers back\n", __FUNCTION__);
++ vnic->frontend_ready = 1;
++ if (vnic->backend_netdev_up)
++ vnic_start_fastpath(vnic);
++ } else {
++ VPRINTK("%s: got buffers back %d %d\n", __FUNCTION__,
++ offset, msg->u.mapbufs.pages);
++ }
++ }
++
++ return rc;
++}
++
++
++/* The largest [o] such that (1u << o) <= n. Requires n > 0. */
++
++inline unsigned log2_le(unsigned long n) {
++ unsigned order = 1;
++ while ((1ul << order) <= n) ++order;
++ return (order - 1);
++}
++
++static int vnic_send_buffer_requests(netfront_accel_vnic *vnic,
++ struct netfront_accel_bufpages *bufpages)
++{
++ int pages, offset, rc = 0, sent = 0;
++ struct net_accel_msg msg;
++
++ while (bufpages->page_reqs < bufpages->max_pages) {
++ offset = bufpages->page_reqs;
++
++ pages = pow2(log2_le(bufpages->max_pages -
++ bufpages->page_reqs));
++ pages = pages < NET_ACCEL_MSG_MAX_PAGE_REQ ?
++ pages : NET_ACCEL_MSG_MAX_PAGE_REQ;
++
++ BUG_ON(offset < 0);
++ BUG_ON(pages <= 0);
++
++ rc = netfront_accel_buf_map_request(vnic->dev, bufpages,
++ &msg, pages, offset);
++ if (rc == 0) {
++ rc = net_accel_msg_send(vnic->shared_page,
++ &vnic->to_dom0, &msg);
++ if (rc < 0) {
++ VPRINTK("%s: queue full, stopping for now\n",
++ __FUNCTION__);
++ break;
++ }
++ sent++;
++ } else {
++ EPRINTK("%s: problem with grant, stopping for now\n",
++ __FUNCTION__);
++ break;
++ }
++
++ bufpages->page_reqs += pages;
++ }
++
++ if (sent)
++ net_accel_msg_notify(vnic->msg_channel_irq);
++
++ return rc;
++}
++
++
++/*
++ * In response to dom0 saying "my queue is full", we reply with this
++ * when it is no longer full
++ */
++inline void vnic_set_queue_not_full(netfront_accel_vnic *vnic)
++{
++
++ if (test_and_set_bit(NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL_B,
++ (unsigned long *)&vnic->shared_page->aflags))
++ notify_remote_via_irq(vnic->msg_channel_irq);
++ else
++ VPRINTK("queue not full bit already set, not signalling\n");
++}
++
++/*
++ * Notify dom0 that the queue we want to use is full, it should
++ * respond by setting MSG_AFLAGS_QUEUEUNOTFULL in due course
++ */
++inline void vnic_set_queue_full(netfront_accel_vnic *vnic)
++{
++
++ if (!test_and_set_bit(NET_ACCEL_MSG_AFLAGS_QUEUEUFULL_B,
++ (unsigned long *)&vnic->shared_page->aflags))
++ notify_remote_via_irq(vnic->msg_channel_irq);
++ else
++ VPRINTK("queue full bit already set, not signalling\n");
++}
++
++
++static int vnic_check_hello_version(unsigned version)
++{
++ if (version > NET_ACCEL_MSG_VERSION) {
++ /* Newer protocol, we must refuse */
++ return -EPROTO;
++ }
++
++ if (version < NET_ACCEL_MSG_VERSION) {
++ /*
++ * We are newer, so have discretion to accept if we
++ * wish. For now however, just reject
++ */
++ return -EPROTO;
++ }
++
++ BUG_ON(version != NET_ACCEL_MSG_VERSION);
++ return 0;
++}
++
++
++static int vnic_process_hello_msg(netfront_accel_vnic *vnic,
++ struct net_accel_msg *msg)
++{
++ int err = 0;
++ unsigned pages = sfc_netfront_max_pages;
++
++ if (vnic_check_hello_version(msg->u.hello.version) < 0) {
++ msg->id = NET_ACCEL_MSG_HELLO | NET_ACCEL_MSG_REPLY
++ | NET_ACCEL_MSG_ERROR;
++ msg->u.hello.version = NET_ACCEL_MSG_VERSION;
++ } else {
++ vnic->backend_netdev_up
++ = vnic->shared_page->net_dev_up;
++
++ msg->id = NET_ACCEL_MSG_HELLO | NET_ACCEL_MSG_REPLY;
++ msg->u.hello.version = NET_ACCEL_MSG_VERSION;
++ if (msg->u.hello.max_pages &&
++ msg->u.hello.max_pages < pages)
++ pages = msg->u.hello.max_pages;
++ msg->u.hello.max_pages = pages;
++
++ /* Half of pages for rx, half for tx */
++ err = netfront_accel_alloc_buffer_mem(&vnic->bufpages,
++ vnic->rx_bufs,
++ vnic->tx_bufs,
++ pages);
++ if (err)
++ msg->id |= NET_ACCEL_MSG_ERROR;
++ }
++
++ /* Send reply */
++ net_accel_msg_reply_notify(vnic->shared_page, vnic->msg_channel_irq,
++ &vnic->to_dom0, msg);
++ return err;
++}
++
++
++static int vnic_process_localmac_msg(netfront_accel_vnic *vnic,
++ struct net_accel_msg *msg)
++{
++ unsigned long flags;
++ cuckoo_hash_mac_key key;
++
++ if (msg->u.localmac.flags & NET_ACCEL_MSG_ADD) {
++ DPRINTK("MAC has moved, could be local: " MAC_FMT "\n",
++ MAC_ARG(msg->u.localmac.mac));
++ key = cuckoo_mac_to_key(msg->u.localmac.mac);
++ spin_lock_irqsave(&vnic->table_lock, flags);
++ /* Try to remove it, not a big deal if not there */
++ cuckoo_hash_remove(&vnic->fastpath_table,
++ (cuckoo_hash_key *)&key);
++ spin_unlock_irqrestore(&vnic->table_lock, flags);
++ }
++
++ return 0;
++}
++
++
++static
++int vnic_process_rx_msg(netfront_accel_vnic *vnic,
++ struct net_accel_msg *msg)
++{
++ int err;
++
++ switch (msg->id) {
++ case NET_ACCEL_MSG_HELLO:
++ /* Hello, reply with Reply */
++ DPRINTK("got Hello, with version %.8x\n",
++ msg->u.hello.version);
++ BUG_ON(vnic->msg_state != NETFRONT_ACCEL_MSG_NONE);
++ err = vnic_process_hello_msg(vnic, msg);
++ if (err == 0)
++ vnic->msg_state = NETFRONT_ACCEL_MSG_HELLO;
++ break;
++ case NET_ACCEL_MSG_SETHW:
++ /* Hardware info message */
++ DPRINTK("got H/W info\n");
++ BUG_ON(vnic->msg_state != NETFRONT_ACCEL_MSG_HELLO);
++ err = netfront_accel_vi_init(vnic, &msg->u.hw);
++ if (err == 0)
++ vnic->msg_state = NETFRONT_ACCEL_MSG_HW;
++ break;
++ case NET_ACCEL_MSG_MAPBUF | NET_ACCEL_MSG_REPLY:
++ VPRINTK("Got mapped buffers back\n");
++ BUG_ON(vnic->msg_state != NETFRONT_ACCEL_MSG_HW);
++ err = vnic_add_bufs(vnic, msg);
++ break;
++ case NET_ACCEL_MSG_MAPBUF | NET_ACCEL_MSG_REPLY | NET_ACCEL_MSG_ERROR:
++ /* No buffers. Can't use the fast path. */
++ EPRINTK("Got mapped buffers error. Cannot accelerate.\n");
++ BUG_ON(vnic->msg_state != NETFRONT_ACCEL_MSG_HW);
++ err = -EIO;
++ break;
++ case NET_ACCEL_MSG_LOCALMAC:
++ /* Should be add, remove not currently used */
++ EPRINTK_ON(!(msg->u.localmac.flags & NET_ACCEL_MSG_ADD));
++ BUG_ON(vnic->msg_state != NETFRONT_ACCEL_MSG_HW);
++ err = vnic_process_localmac_msg(vnic, msg);
++ break;
++ default:
++ EPRINTK("Huh? Message code is 0x%x\n", msg->id);
++ err = -EPROTO;
++ break;
++ }
++
++ return err;
++}
++
++
++/* Process an IRQ received from back end driver */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++void netfront_accel_msg_from_bend(struct work_struct *context)
++#else
++void netfront_accel_msg_from_bend(void *context)
++#endif
++{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ netfront_accel_vnic *vnic =
++ container_of(context, netfront_accel_vnic, msg_from_bend);
++#else
++ netfront_accel_vnic *vnic = (netfront_accel_vnic *)context;
++#endif
++ struct net_accel_msg msg;
++ int err, queue_was_full = 0;
++
++ mutex_lock(&vnic->vnic_mutex);
++
++ /*
++ * This happens when the shared pages have been unmapped but
++ * the workqueue has yet to be flushed
++ */
++ if (!vnic->dom0_state_is_setup)
++ goto unlock_out;
++
++ while ((vnic->shared_page->aflags & NET_ACCEL_MSG_AFLAGS_TO_DOMU_MASK)
++ != 0) {
++ if (vnic->shared_page->aflags &
++ NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL) {
++ /* We've been told there may now be space. */
++ clear_bit(NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL_B,
++ (unsigned long *)&vnic->shared_page->aflags);
++ }
++
++ if (vnic->shared_page->aflags &
++ NET_ACCEL_MSG_AFLAGS_QUEUE0FULL) {
++ /*
++ * There will be space at the end of this
++ * function if we can make any.
++ */
++ clear_bit(NET_ACCEL_MSG_AFLAGS_QUEUE0FULL_B,
++ (unsigned long *)&vnic->shared_page->aflags);
++ queue_was_full = 1;
++ }
++
++ if (vnic->shared_page->aflags &
++ NET_ACCEL_MSG_AFLAGS_NETUPDOWN) {
++ DPRINTK("%s: net interface change\n", __FUNCTION__);
++ clear_bit(NET_ACCEL_MSG_AFLAGS_NETUPDOWN_B,
++ (unsigned long *)&vnic->shared_page->aflags);
++ if (vnic->shared_page->net_dev_up)
++ netfront_accel_interface_up(vnic);
++ else
++ netfront_accel_interface_down(vnic);
++ }
++ }
++
++ /* Pull msg out of shared memory */
++ while ((err = net_accel_msg_recv(vnic->shared_page, &vnic->from_dom0,
++ &msg)) == 0) {
++ err = vnic_process_rx_msg(vnic, &msg);
++
++ if (err != 0)
++ goto done;
++ }
++
++ /*
++ * Send any pending buffer map request messages that we can,
++ * and mark domU->dom0 as full if necessary.
++ */
++ if (vnic->msg_state == NETFRONT_ACCEL_MSG_HW &&
++ vnic->bufpages.page_reqs < vnic->bufpages.max_pages) {
++ if (vnic_send_buffer_requests(vnic, &vnic->bufpages) == -ENOSPC)
++ vnic_set_queue_full(vnic);
++ }
++
++ /*
++ * If there are no messages then this is not an error. It
++ * just means that we've finished processing the queue.
++ */
++ if (err == -ENOENT)
++ err = 0;
++ done:
++ /* We will now have made space in the dom0->domU queue if we can */
++ if (queue_was_full)
++ vnic_set_queue_not_full(vnic);
++
++ if (err != 0) {
++ EPRINTK("%s returned %d\n", __FUNCTION__, err);
++ netfront_accel_set_closing(vnic);
++ }
++
++ unlock_out:
++ mutex_unlock(&vnic->vnic_mutex);
++
++ return;
++}
++
++
++irqreturn_t netfront_accel_msg_channel_irq_from_bend(int irq, void *context,
++ struct pt_regs *unused)
++{
++ netfront_accel_vnic *vnic = (netfront_accel_vnic *)context;
++ VPRINTK("irq %d from device %s\n", irq, vnic->dev->nodename);
++
++ queue_work(netfront_accel_workqueue, &vnic->msg_from_bend);
++
++ return IRQ_HANDLED;
++}
++
++/* Process an interrupt received from the NIC via backend */
++irqreturn_t netfront_accel_net_channel_irq_from_bend(int irq, void *context,
++ struct pt_regs *unused)
++{
++ netfront_accel_vnic *vnic = (netfront_accel_vnic *)context;
++ struct net_device *net_dev = vnic->net_dev;
++ unsigned long flags;
++
++ VPRINTK("net irq %d from device %s\n", irq, vnic->dev->nodename);
++
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.irq_count++);
++
++ BUG_ON(net_dev==NULL);
++
++ spin_lock_irqsave(&vnic->irq_enabled_lock, flags);
++ if (vnic->irq_enabled) {
++ netfront_accel_disable_net_interrupts(vnic);
++ vnic->irq_enabled = 0;
++ spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
++
++#if NETFRONT_ACCEL_STATS
++ vnic->stats.poll_schedule_count++;
++ if (vnic->stats.event_count_since_irq >
++ vnic->stats.events_per_irq_max)
++ vnic->stats.events_per_irq_max =
++ vnic->stats.event_count_since_irq;
++ vnic->stats.event_count_since_irq = 0;
++#endif
++ netif_rx_schedule(net_dev);
++ }
++ else {
++ spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.useless_irq_count++);
++ DPRINTK("%s: irq when disabled\n", __FUNCTION__);
++ }
++
++ return IRQ_HANDLED;
++}
++
++
++void netfront_accel_msg_tx_fastpath(netfront_accel_vnic *vnic, const void *mac,
++ u32 ip, u16 port, u8 protocol)
++{
++ unsigned long lock_state;
++ struct net_accel_msg *msg;
++
++ msg = net_accel_msg_start_send(vnic->shared_page, &vnic->to_dom0,
++ &lock_state);
++
++ if (msg == NULL)
++ return;
++
++ net_accel_msg_init(msg, NET_ACCEL_MSG_FASTPATH);
++ msg->u.fastpath.flags = NET_ACCEL_MSG_REMOVE;
++ memcpy(msg->u.fastpath.mac, mac, ETH_ALEN);
++
++ msg->u.fastpath.port = port;
++ msg->u.fastpath.ip = ip;
++ msg->u.fastpath.proto = protocol;
++
++ net_accel_msg_complete_send_notify(vnic->shared_page, &vnic->to_dom0,
++ &lock_state, vnic->msg_channel_irq);
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_netfront.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_netfront.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_netfront.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_netfront.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,319 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++
++/* drivers/xen/netfront/netfront.h */
++#include "netfront.h"
++
++#include "accel.h"
++#include "accel_bufs.h"
++#include "accel_util.h"
++#include "accel_msg_iface.h"
++#include "accel_ssr.h"
++
++#ifdef EFX_GCOV
++#include "gcov.h"
++#endif
++
++#define NETFRONT_ACCEL_VNIC_FROM_NETDEV(_nd) \
++ ((netfront_accel_vnic *)((struct netfront_info *)netdev_priv(net_dev))->accel_priv)
++
++static int netfront_accel_netdev_start_xmit(struct sk_buff *skb,
++ struct net_device *net_dev)
++{
++ netfront_accel_vnic *vnic = NETFRONT_ACCEL_VNIC_FROM_NETDEV(net_dev);
++ struct netfront_info *np =
++ (struct netfront_info *)netdev_priv(net_dev);
++ int handled, rc;
++ unsigned long flags1, flags2;
++
++ BUG_ON(vnic == NULL);
++
++ /* Take our tx lock and hold for the duration */
++ spin_lock_irqsave(&vnic->tx_lock, flags1);
++
++ if (!vnic->tx_enabled) {
++ rc = 0;
++ goto unlock_out;
++ }
++
++ handled = netfront_accel_vi_tx_post(vnic, skb);
++ if (handled == NETFRONT_ACCEL_STATUS_BUSY) {
++ BUG_ON(vnic->net_dev != net_dev);
++ DPRINTK("%s stopping queue\n", __FUNCTION__);
++
++ /* Netfront's lock protects tx_skb */
++ spin_lock_irqsave(&np->tx_lock, flags2);
++ BUG_ON(vnic->tx_skb != NULL);
++ vnic->tx_skb = skb;
++ netif_stop_queue(net_dev);
++ spin_unlock_irqrestore(&np->tx_lock, flags2);
++
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.queue_stops++);
++ }
++
++ if (handled == NETFRONT_ACCEL_STATUS_CANT)
++ rc = 0;
++ else
++ rc = 1;
++
++unlock_out:
++ spin_unlock_irqrestore(&vnic->tx_lock, flags1);
++
++ return rc;
++}
++
++
++static int netfront_accel_netdev_poll(struct net_device *net_dev, int *budget)
++{
++ netfront_accel_vnic *vnic = NETFRONT_ACCEL_VNIC_FROM_NETDEV(net_dev);
++ int rx_allowed = *budget, rx_done;
++
++ BUG_ON(vnic == NULL);
++
++ /* Can check this without lock as modifier excludes polls */
++ if (!vnic->poll_enabled)
++ return 0;
++
++ rx_done = netfront_accel_vi_poll(vnic, rx_allowed);
++ *budget -= rx_done;
++
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.poll_call_count++);
++
++ VPRINTK("%s: done %d allowed %d\n",
++ __FUNCTION__, rx_done, rx_allowed);
++
++ netfront_accel_ssr_end_of_burst(vnic, &vnic->ssr_state);
++
++ if (rx_done < rx_allowed) {
++ return 0; /* Done */
++ }
++
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.poll_reschedule_count++);
++
++ return 1; /* More to do. */
++}
++
++
++/*
++ * Process request from netfront to start napi interrupt
++ * mode. (i.e. enable interrupts as it's finished polling)
++ */
++static int netfront_accel_start_napi_interrupts(struct net_device *net_dev)
++{
++ netfront_accel_vnic *vnic = NETFRONT_ACCEL_VNIC_FROM_NETDEV(net_dev);
++ unsigned long flags;
++
++ BUG_ON(vnic == NULL);
++
++ /*
++ * Can check this without lock as writer excludes poll before
++ * modifying
++ */
++ if (!vnic->poll_enabled)
++ return 0;
++
++ if (!netfront_accel_vi_enable_interrupts(vnic)) {
++ /*
++ * There was something there, tell caller we had
++ * something to do.
++ */
++ return 1;
++ }
++
++ spin_lock_irqsave(&vnic->irq_enabled_lock, flags);
++ vnic->irq_enabled = 1;
++ netfront_accel_enable_net_interrupts(vnic);
++ spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
++
++ return 0;
++}
++
++
++/*
++ * Process request from netfront to stop napi interrupt
++ * mode. (i.e. disable interrupts as it's starting to poll
++ */
++static void netfront_accel_stop_napi_interrupts(struct net_device *net_dev)
++{
++ netfront_accel_vnic *vnic = NETFRONT_ACCEL_VNIC_FROM_NETDEV(net_dev);
++ unsigned long flags;
++
++ BUG_ON(vnic == NULL);
++
++ spin_lock_irqsave(&vnic->irq_enabled_lock, flags);
++
++ if (!vnic->poll_enabled) {
++ spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
++ return;
++ }
++
++ netfront_accel_disable_net_interrupts(vnic);
++ vnic->irq_enabled = 0;
++ spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
++}
++
++
++static int netfront_accel_check_ready(struct net_device *net_dev)
++{
++ netfront_accel_vnic *vnic = NETFRONT_ACCEL_VNIC_FROM_NETDEV(net_dev);
++
++ BUG_ON(vnic == NULL);
++
++ /* This is protected by netfront's lock */
++ return vnic->tx_skb == NULL;
++}
++
++
++static int netfront_accel_get_stats(struct net_device *net_dev,
++ struct net_device_stats *stats)
++{
++ netfront_accel_vnic *vnic = NETFRONT_ACCEL_VNIC_FROM_NETDEV(net_dev);
++ struct netfront_accel_netdev_stats now;
++
++ BUG_ON(vnic == NULL);
++
++ now.fastpath_rx_pkts = vnic->netdev_stats.fastpath_rx_pkts;
++ now.fastpath_rx_bytes = vnic->netdev_stats.fastpath_rx_bytes;
++ now.fastpath_rx_errors = vnic->netdev_stats.fastpath_rx_errors;
++ now.fastpath_tx_pkts = vnic->netdev_stats.fastpath_tx_pkts;
++ now.fastpath_tx_bytes = vnic->netdev_stats.fastpath_tx_bytes;
++ now.fastpath_tx_errors = vnic->netdev_stats.fastpath_tx_errors;
++
++ stats->rx_packets += (now.fastpath_rx_pkts -
++ vnic->stats_last_read.fastpath_rx_pkts);
++ stats->rx_bytes += (now.fastpath_rx_bytes -
++ vnic->stats_last_read.fastpath_rx_bytes);
++ stats->rx_errors += (now.fastpath_rx_errors -
++ vnic->stats_last_read.fastpath_rx_errors);
++ stats->tx_packets += (now.fastpath_tx_pkts -
++ vnic->stats_last_read.fastpath_tx_pkts);
++ stats->tx_bytes += (now.fastpath_tx_bytes -
++ vnic->stats_last_read.fastpath_tx_bytes);
++ stats->tx_errors += (now.fastpath_tx_errors -
++ vnic->stats_last_read.fastpath_tx_errors);
++
++ vnic->stats_last_read = now;
++
++ return 0;
++}
++
++
++struct netfront_accel_hooks accel_hooks = {
++ .new_device = &netfront_accel_probe,
++ .remove = &netfront_accel_remove,
++ .netdev_poll = &netfront_accel_netdev_poll,
++ .start_xmit = &netfront_accel_netdev_start_xmit,
++ .start_napi_irq = &netfront_accel_start_napi_interrupts,
++ .stop_napi_irq = &netfront_accel_stop_napi_interrupts,
++ .check_ready = &netfront_accel_check_ready,
++ .get_stats = &netfront_accel_get_stats
++};
++
++
++unsigned sfc_netfront_max_pages = NETFRONT_ACCEL_DEFAULT_BUF_PAGES;
++module_param_named (max_pages, sfc_netfront_max_pages, uint, 0644);
++MODULE_PARM_DESC(max_pages, "Number of buffer pages to request");
++
++unsigned sfc_netfront_buffer_split = 2;
++module_param_named (buffer_split, sfc_netfront_buffer_split, uint, 0644);
++MODULE_PARM_DESC(buffer_split,
++ "Fraction of buffers to use for TX, rest for RX");
++
++
++const char *frontend_name = "sfc_netfront";
++
++struct workqueue_struct *netfront_accel_workqueue;
++
++static int __init netfront_accel_init(void)
++{
++ int rc;
++#ifdef EFX_GCOV
++ gcov_provider_init(THIS_MODULE);
++#endif
++
++ /*
++ * If we're running on dom0, netfront hasn't initialised
++ * itself, so we need to keep away
++ */
++ if (is_initial_xendomain())
++ return 0;
++
++ if (!is_pow2(sizeof(struct net_accel_msg)))
++ EPRINTK("%s: bad structure size\n", __FUNCTION__);
++
++ netfront_accel_workqueue = create_workqueue(frontend_name);
++
++ netfront_accel_debugfs_init();
++
++ rc = netfront_accelerator_loaded(NETFRONT_ACCEL_VERSION,
++ frontend_name, &accel_hooks);
++
++ if (rc < 0) {
++ EPRINTK("Xen netfront accelerator version mismatch\n");
++ return -EINVAL;
++ }
++
++ if (rc > 0) {
++ /*
++ * In future may want to add backwards compatibility
++ * and accept certain subsets of previous versions
++ */
++ EPRINTK("Xen netfront accelerator version mismatch\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++module_init(netfront_accel_init);
++
++static void __exit netfront_accel_exit(void)
++{
++ if (is_initial_xendomain())
++ return;
++
++ DPRINTK("%s: unhooking\n", __FUNCTION__);
++
++ /* Unhook from normal netfront */
++ netfront_accelerator_stop(frontend_name);
++
++ DPRINTK("%s: done\n", __FUNCTION__);
++
++ netfront_accel_debugfs_fini();
++
++ flush_workqueue(netfront_accel_workqueue);
++
++ destroy_workqueue(netfront_accel_workqueue);
++
++#ifdef EFX_GCOV
++ gcov_provider_fini(THIS_MODULE);
++#endif
++ return;
++}
++module_exit(netfront_accel_exit);
++
++MODULE_LICENSE("GPL");
++
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_ssr.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_ssr.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_ssr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_ssr.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,308 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/list.h>
++#include <net/ip.h>
++#include <net/checksum.h>
++
++#include "accel.h"
++#include "accel_util.h"
++#include "accel_bufs.h"
++
++#include "accel_ssr.h"
++
++static inline int list_valid(struct list_head *lh) {
++ return(lh->next != NULL);
++}
++
++static void netfront_accel_ssr_deliver (struct netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st,
++ struct netfront_accel_ssr_conn *c);
++
++/** Construct an efx_ssr_state.
++ *
++ * @v st The SSR state (per channel per port)
++ * @v port The port.
++ */
++void netfront_accel_ssr_init(struct netfront_accel_ssr_state *st) {
++ unsigned i;
++
++ INIT_LIST_HEAD(&st->conns);
++ INIT_LIST_HEAD(&st->free_conns);
++ for (i = 0; i < 8; ++i) {
++ struct netfront_accel_ssr_conn *c =
++ kmalloc(sizeof(*c), GFP_KERNEL);
++ if (c == NULL) break;
++ c->n_in_order_pkts = 0;
++ c->skb = NULL;
++ list_add(&c->link, &st->free_conns);
++ }
++
++}
++
++
++/** Destructor for an efx_ssr_state.
++ *
++ * @v st The SSR state (per channel per port)
++ */
++void netfront_accel_ssr_fini(netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st) {
++ struct netfront_accel_ssr_conn *c;
++
++ /* Return cleanly if efx_ssr_init() not previously called */
++ BUG_ON(list_valid(&st->conns) != list_valid(&st->free_conns));
++ if (! list_valid(&st->conns))
++ return;
++
++ while ( ! list_empty(&st->free_conns)) {
++ c = list_entry(st->free_conns.prev,
++ struct netfront_accel_ssr_conn, link);
++ list_del(&c->link);
++ BUG_ON(c->skb != NULL);
++ kfree(c);
++ }
++ while ( ! list_empty(&st->conns)) {
++ c = list_entry(st->conns.prev,
++ struct netfront_accel_ssr_conn, link);
++ list_del(&c->link);
++ if (c->skb)
++ netfront_accel_ssr_deliver(vnic, st, c);
++ kfree(c);
++ }
++}
++
++
++/** Calc IP checksum and deliver to the OS
++ *
++ * @v st The SSR state (per channel per port)
++ * @v c The SSR connection state
++ */
++static void netfront_accel_ssr_deliver(netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st,
++ struct netfront_accel_ssr_conn *c) {
++ BUG_ON(c->skb == NULL);
++
++ /*
++ * If we've chained packets together, recalculate the IP
++ * checksum.
++ */
++ if (skb_shinfo(c->skb)->frag_list) {
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.ssr_bursts);
++ c->iph->check = 0;
++ c->iph->check = ip_fast_csum((unsigned char *) c->iph,
++ c->iph->ihl);
++ }
++
++ VPRINTK("%s: %d\n", __FUNCTION__, c->skb->len);
++
++ netif_receive_skb(c->skb);
++ c->skb = NULL;
++}
++
++
++/** Push held skbs down into network stack.
++ *
++ * @v st SSR state
++ *
++ * Only called if we are tracking one or more connections.
++ */
++void __netfront_accel_ssr_end_of_burst(netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st) {
++ struct netfront_accel_ssr_conn *c;
++
++ BUG_ON(list_empty(&st->conns));
++
++ list_for_each_entry(c, &st->conns, link)
++ if (c->skb)
++ netfront_accel_ssr_deliver(vnic, st, c);
++
++ /* Time-out connections that have received no traffic for 20ms. */
++ c = list_entry(st->conns.prev, struct netfront_accel_ssr_conn,
++ link);
++ if (jiffies - c->last_pkt_jiffies > (HZ / 50 + 1)) {
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.ssr_drop_stream);
++ list_del(&c->link);
++ list_add(&c->link, &st->free_conns);
++ }
++}
++
++
++/** Process SKB and decide whether to dispatch it to the stack now or
++ * later.
++ *
++ * @v st SSR state
++ * @v skb SKB to exmaine
++ * @ret rc 0 => deliver SKB to kernel now, otherwise the SKB belongs
++ * us.
++ */
++int netfront_accel_ssr_skb(struct netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st,
++ struct sk_buff *skb) {
++ int data_length, dont_merge;
++ struct netfront_accel_ssr_conn *c;
++ struct iphdr *iph;
++ struct tcphdr *th;
++ unsigned th_seq;
++
++ BUG_ON(skb_shinfo(skb)->frag_list != NULL);
++ BUG_ON(skb->next != NULL);
++
++ /* We're not interested if it isn't TCP over IPv4. */
++ iph = (struct iphdr *) skb->data;
++ if (skb->protocol != htons(ETH_P_IP) ||
++ iph->protocol != IPPROTO_TCP) {
++ return 0;
++ }
++
++ /* Ignore segments that fail csum or are fragmented. */
++ if (unlikely((skb->ip_summed - CHECKSUM_UNNECESSARY) |
++ (iph->frag_off & htons(IP_MF | IP_OFFSET)))) {
++ return 0;
++ }
++
++ th = (struct tcphdr*)(skb->data + iph->ihl * 4);
++ data_length = ntohs(iph->tot_len) - iph->ihl * 4 - th->doff * 4;
++ th_seq = ntohl(th->seq);
++ dont_merge = (data_length == 0) | th->urg | th->syn | th->rst;
++
++ list_for_each_entry(c, &st->conns, link) {
++ if ((c->saddr - iph->saddr) |
++ (c->daddr - iph->daddr) |
++ (c->source - th->source) |
++ (c->dest - th->dest ))
++ continue;
++
++ /* Re-insert at head of list to reduce lookup time. */
++ list_del(&c->link);
++ list_add(&c->link, &st->conns);
++ c->last_pkt_jiffies = jiffies;
++
++ if (unlikely(th_seq - c->next_seq)) {
++ /* Out-of-order, so start counting again. */
++ if (c->skb)
++ netfront_accel_ssr_deliver(vnic, st, c);
++ c->n_in_order_pkts = 0;
++ c->next_seq = th_seq + data_length;
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.ssr_misorder);
++ return 0;
++ }
++ c->next_seq = th_seq + data_length;
++
++ if (++c->n_in_order_pkts < 300) {
++ /* May be in slow-start, so don't merge. */
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.ssr_slow_start);
++ return 0;
++ }
++
++ if (unlikely(dont_merge)) {
++ if (c->skb)
++ netfront_accel_ssr_deliver(vnic, st, c);
++ return 0;
++ }
++
++ if (c->skb) {
++ c->iph->tot_len = ntohs(c->iph->tot_len);
++ c->iph->tot_len += data_length;
++ c->iph->tot_len = htons(c->iph->tot_len);
++ c->th->ack_seq = th->ack_seq;
++ c->th->fin |= th->fin;
++ c->th->psh |= th->psh;
++ c->th->window = th->window;
++
++ /* Remove the headers from this skb. */
++ skb_pull(skb, skb->len - data_length);
++
++ /*
++ * Tack the new skb onto the head skb's frag_list.
++ * This is exactly the format that fragmented IP
++ * datagrams are reassembled into.
++ */
++ BUG_ON(skb->next != 0);
++ if ( ! skb_shinfo(c->skb)->frag_list)
++ skb_shinfo(c->skb)->frag_list = skb;
++ else
++ c->skb_tail->next = skb;
++ c->skb_tail = skb;
++ c->skb->len += skb->len;
++ c->skb->data_len += skb->len;
++ c->skb->truesize += skb->truesize;
++
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.ssr_merges);
++
++ /*
++ * If the next packet might push this super-packet
++ * over the limit for an IP packet, deliver it now.
++ * This is slightly conservative, but close enough.
++ */
++ if (c->skb->len +
++ (PAGE_SIZE / NETFRONT_ACCEL_BUFS_PER_PAGE)
++ > 16384)
++ netfront_accel_ssr_deliver(vnic, st, c);
++
++ return 1;
++ }
++ else {
++ c->iph = iph;
++ c->th = th;
++ c->skb = skb;
++ return 1;
++ }
++ }
++
++ /* We're not yet tracking this connection. */
++
++ if (dont_merge) {
++ return 0;
++ }
++
++ if (list_empty(&st->free_conns)) {
++ c = list_entry(st->conns.prev,
++ struct netfront_accel_ssr_conn,
++ link);
++ if (c->skb) {
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.ssr_too_many);
++ return 0;
++ }
++ }
++ else {
++ c = list_entry(st->free_conns.next,
++ struct netfront_accel_ssr_conn,
++ link);
++ }
++ list_del(&c->link);
++ list_add(&c->link, &st->conns);
++ c->saddr = iph->saddr;
++ c->daddr = iph->daddr;
++ c->source = th->source;
++ c->dest = th->dest;
++ c->next_seq = th_seq + data_length;
++ c->n_in_order_pkts = 0;
++ BUG_ON(c->skb != NULL);
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.ssr_new_stream);
++ return 0;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_ssr.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_ssr.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_ssr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_ssr.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,88 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NETFRONT_ACCEL_SSR_H
++#define NETFRONT_ACCEL_SSR_H
++
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/list.h>
++
++#include "accel.h"
++
++/** State for Soft Segment Reassembly (SSR). */
++
++struct netfront_accel_ssr_conn {
++ struct list_head link;
++
++ unsigned saddr, daddr;
++ unsigned short source, dest;
++
++ /** Number of in-order packets we've seen with payload. */
++ unsigned n_in_order_pkts;
++
++ /** Next in-order sequence number. */
++ unsigned next_seq;
++
++ /** Time we last saw a packet on this connection. */
++ unsigned long last_pkt_jiffies;
++
++ /** The SKB we are currently holding. If NULL, then all following
++ * fields are undefined.
++ */
++ struct sk_buff *skb;
++
++ /** The tail of the frag_list of SKBs we're holding. Only valid
++ * after at least one merge.
++ */
++ struct sk_buff *skb_tail;
++
++ /** The IP header of the skb we are holding. */
++ struct iphdr *iph;
++
++ /** The TCP header of the skb we are holding. */
++ struct tcphdr *th;
++};
++
++extern void netfront_accel_ssr_init(struct netfront_accel_ssr_state *st);
++extern void netfront_accel_ssr_fini(netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st);
++
++extern void
++__netfront_accel_ssr_end_of_burst(netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st);
++
++extern int netfront_accel_ssr_skb(netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st,
++ struct sk_buff *skb);
++
++static inline void
++netfront_accel_ssr_end_of_burst (netfront_accel_vnic *vnic,
++ struct netfront_accel_ssr_state *st) {
++ if ( ! list_empty(&st->conns) )
++ __netfront_accel_ssr_end_of_burst(vnic, st);
++}
++
++#endif /* NETFRONT_ACCEL_SSR_H */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_tso.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_tso.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_tso.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_tso.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,511 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/pci.h>
++#include <linux/tcp.h>
++#include <linux/ip.h>
++#include <linux/in.h>
++#include <linux/if_ether.h>
++
++#include "accel.h"
++#include "accel_util.h"
++
++#include "accel_tso.h"
++
++#define PTR_DIFF(p1, p2) ((u8*)(p1) - (u8*)(p2))
++#define ETH_HDR_LEN(skb) ((skb)->nh.raw - (skb)->data)
++#define SKB_TCP_OFF(skb) PTR_DIFF ((skb)->h.th, (skb)->data)
++#define SKB_IP_OFF(skb) PTR_DIFF ((skb)->nh.iph, (skb)->data)
++
++/*
++ * Set a maximum number of buffers in each output packet to make life
++ * a little simpler - if this is reached it will just move on to
++ * another packet
++ */
++#define ACCEL_TSO_MAX_BUFFERS (6)
++
++/** TSO State.
++ *
++ * The state used during segmentation. It is put into this data structure
++ * just to make it easy to pass into inline functions.
++ */
++struct netfront_accel_tso_state {
++ /** bytes of data we've yet to segment */
++ unsigned remaining_len;
++
++ /** current sequence number */
++ unsigned seqnum;
++
++ /** remaining space in current packet */
++ unsigned packet_space;
++
++ /** List of packets to be output, containing the buffers and
++ * iovecs to describe each packet
++ */
++ struct netfront_accel_tso_output_packet *output_packets;
++
++ /** Total number of buffers in output_packets */
++ unsigned buffers;
++
++ /** Total number of packets in output_packets */
++ unsigned packets;
++
++ /** Input Fragment Cursor.
++ *
++ * Where we are in the current fragment of the incoming SKB. These
++ * values get updated in place when we split a fragment over
++ * multiple packets.
++ */
++ struct {
++ /** address of current position */
++ void *addr;
++ /** remaining length */
++ unsigned int len;
++ } ifc; /* == ifc Input Fragment Cursor */
++
++ /** Parameters.
++ *
++ * These values are set once at the start of the TSO send and do
++ * not get changed as the routine progresses.
++ */
++ struct {
++ /* the number of bytes of header */
++ unsigned int header_length;
++
++ /* The number of bytes to put in each outgoing segment. */
++ int full_packet_size;
++
++ /* Current IP ID, host endian. */
++ unsigned ip_id;
++
++ /* Max size of each output packet payload */
++ int gso_size;
++ } p;
++};
++
++
++/**
++ * Verify that our various assumptions about sk_buffs and the conditions
++ * under which TSO will be attempted hold true.
++ *
++ * @v skb The sk_buff to check.
++ */
++static inline void tso_check_safe(struct sk_buff *skb) {
++ EPRINTK_ON(skb->protocol != htons (ETH_P_IP));
++ EPRINTK_ON(((struct ethhdr*) skb->data)->h_proto != htons (ETH_P_IP));
++ EPRINTK_ON(skb->nh.iph->protocol != IPPROTO_TCP);
++ EPRINTK_ON((SKB_TCP_OFF(skb)
++ + (skb->h.th->doff << 2u)) > skb_headlen(skb));
++}
++
++
++
++/** Parse the SKB header and initialise state. */
++static inline void tso_start(struct netfront_accel_tso_state *st,
++ struct sk_buff *skb) {
++
++ /*
++ * All ethernet/IP/TCP headers combined size is TCP header size
++ * plus offset of TCP header relative to start of packet.
++ */
++ st->p.header_length = (skb->h.th->doff << 2u) + SKB_TCP_OFF(skb);
++ st->p.full_packet_size = (st->p.header_length
++ + skb_shinfo(skb)->gso_size);
++ st->p.gso_size = skb_shinfo(skb)->gso_size;
++
++ st->p.ip_id = htons(skb->nh.iph->id);
++ st->seqnum = ntohl(skb->h.th->seq);
++
++ EPRINTK_ON(skb->h.th->urg);
++ EPRINTK_ON(skb->h.th->syn);
++ EPRINTK_ON(skb->h.th->rst);
++
++ st->remaining_len = skb->len - st->p.header_length;
++
++ st->output_packets = NULL;
++ st->buffers = 0;
++ st->packets = 0;
++
++ VPRINTK("Starting new TSO: hl %d ps %d gso %d seq %x len %d\n",
++ st->p.header_length, st->p.full_packet_size, st->p.gso_size,
++ st->seqnum, skb->len);
++}
++
++/**
++ * Add another NIC mapped buffer onto an output packet
++ */
++static inline int tso_start_new_buffer(netfront_accel_vnic *vnic,
++ struct netfront_accel_tso_state *st,
++ int first)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++ struct netfront_accel_pkt_desc *buf;
++
++ /* Get a mapped packet buffer */
++ buf = netfront_accel_buf_get(vnic->tx_bufs);
++ if (buf == NULL) {
++ DPRINTK("%s: No buffer for TX\n", __FUNCTION__);
++ return -1;
++ }
++
++ /* Store a bit of meta-data at the end */
++ tso_buf =(struct netfront_accel_tso_buffer *)
++ (buf->pkt_kva + NETFRONT_ACCEL_TSO_BUF_LENGTH
++ + sizeof(struct netfront_accel_tso_output_packet));
++
++ tso_buf->buf = buf;
++
++ tso_buf->length = 0;
++
++ if (first) {
++ struct netfront_accel_tso_output_packet *output_packet
++ = (struct netfront_accel_tso_output_packet *)
++ (buf->pkt_kva + NETFRONT_ACCEL_TSO_BUF_LENGTH);
++ output_packet->next = st->output_packets;
++ st->output_packets = output_packet;
++ tso_buf->next = NULL;
++ st->output_packets->tso_bufs = tso_buf;
++ st->output_packets->tso_bufs_len = 1;
++ } else {
++ tso_buf->next = st->output_packets->tso_bufs;
++ st->output_packets->tso_bufs = tso_buf;
++ st->output_packets->tso_bufs_len ++;
++ }
++
++ BUG_ON(st->output_packets->tso_bufs_len > ACCEL_TSO_MAX_BUFFERS);
++
++ st->buffers ++;
++
++ /*
++ * Store the context, set to NULL, last packet buffer will get
++ * non-NULL later
++ */
++ tso_buf->buf->skb = NULL;
++
++ return 0;
++}
++
++
++/* Generate a new header, and prepare for the new packet.
++ *
++ * @v vnic VNIC
++ * @v skb Socket buffer
++ * @v st TSO state
++ * @ret rc 0 on success, or -1 if failed to alloc header
++ */
++
++static inline
++int tso_start_new_packet(netfront_accel_vnic *vnic,
++ struct sk_buff *skb,
++ struct netfront_accel_tso_state *st)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++ struct iphdr *tsoh_iph;
++ struct tcphdr *tsoh_th;
++ unsigned ip_length;
++
++ if (tso_start_new_buffer(vnic, st, 1) < 0) {
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.fastpath_tx_busy++);
++ return -1;
++ }
++
++ /* This has been set up by tso_start_new_buffer() */
++ tso_buf = st->output_packets->tso_bufs;
++
++ /* Copy in the header */
++ memcpy(tso_buf->buf->pkt_kva, skb->data, st->p.header_length);
++ tso_buf->length = st->p.header_length;
++
++ tsoh_th = (struct tcphdr*)
++ (tso_buf->buf->pkt_kva + SKB_TCP_OFF(skb));
++ tsoh_iph = (struct iphdr*)
++ (tso_buf->buf->pkt_kva + SKB_IP_OFF(skb));
++
++ /* Set to zero to encourage falcon to fill these in */
++ tsoh_th->check = 0;
++ tsoh_iph->check = 0;
++
++ tsoh_th->seq = htonl(st->seqnum);
++ st->seqnum += st->p.gso_size;
++
++ if (st->remaining_len > st->p.gso_size) {
++ /* This packet will not finish the TSO burst. */
++ ip_length = st->p.full_packet_size - ETH_HDR_LEN(skb);
++ tsoh_th->fin = 0;
++ tsoh_th->psh = 0;
++ } else {
++ /* This packet will be the last in the TSO burst. */
++ ip_length = (st->p.header_length - ETH_HDR_LEN(skb)
++ + st->remaining_len);
++ tsoh_th->fin = skb->h.th->fin;
++ tsoh_th->psh = skb->h.th->psh;
++ }
++
++ tsoh_iph->tot_len = htons(ip_length);
++
++ /* Linux leaves suitable gaps in the IP ID space for us to fill. */
++ tsoh_iph->id = st->p.ip_id++;
++ tsoh_iph->id = htons(tsoh_iph->id);
++
++ st->packet_space = st->p.gso_size;
++
++ st->packets++;
++
++ return 0;
++}
++
++
++
++static inline void tso_get_fragment(struct netfront_accel_tso_state *st,
++ int len, void *addr)
++{
++ st->ifc.len = len;
++ st->ifc.addr = addr;
++ return;
++}
++
++
++static inline void tso_unwind(netfront_accel_vnic *vnic,
++ struct netfront_accel_tso_state *st)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++ struct netfront_accel_tso_output_packet *output_packet;
++
++ DPRINTK("%s\n", __FUNCTION__);
++
++ while (st->output_packets != NULL) {
++ output_packet = st->output_packets;
++ st->output_packets = output_packet->next;
++ while (output_packet->tso_bufs != NULL) {
++ tso_buf = output_packet->tso_bufs;
++ output_packet->tso_bufs = tso_buf->next;
++
++ st->buffers --;
++ output_packet->tso_bufs_len --;
++
++ netfront_accel_buf_put(vnic->tx_bufs,
++ tso_buf->buf->buf_id);
++ }
++ }
++ BUG_ON(st->buffers != 0);
++}
++
++
++
++static inline
++void tso_fill_packet_with_fragment(netfront_accel_vnic *vnic,
++ struct netfront_accel_tso_state *st)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++ int n, space;
++
++ BUG_ON(st->output_packets == NULL);
++ BUG_ON(st->output_packets->tso_bufs == NULL);
++
++ tso_buf = st->output_packets->tso_bufs;
++
++ if (st->ifc.len == 0) return;
++ if (st->packet_space == 0) return;
++ if (tso_buf->length == NETFRONT_ACCEL_TSO_BUF_LENGTH) return;
++
++ n = min(st->ifc.len, st->packet_space);
++
++ space = NETFRONT_ACCEL_TSO_BUF_LENGTH - tso_buf->length;
++ n = min(n, space);
++
++ st->packet_space -= n;
++ st->remaining_len -= n;
++ st->ifc.len -= n;
++
++ memcpy(tso_buf->buf->pkt_kva + tso_buf->length, st->ifc.addr, n);
++
++ tso_buf->length += n;
++
++ BUG_ON(tso_buf->length > NETFRONT_ACCEL_TSO_BUF_LENGTH);
++
++ st->ifc.addr += n;
++
++ return;
++}
++
++
++int netfront_accel_enqueue_skb_tso(netfront_accel_vnic *vnic,
++ struct sk_buff *skb)
++{
++ struct netfront_accel_tso_state state;
++ struct netfront_accel_tso_buffer *tso_buf = NULL;
++ struct netfront_accel_tso_output_packet *reversed_list = NULL;
++ struct netfront_accel_tso_output_packet *tmp_pkt;
++ ef_iovec iovecs[ACCEL_TSO_MAX_BUFFERS];
++ int frag_i, rc, dma_id;
++ skb_frag_t *f;
++
++ tso_check_safe(skb);
++
++ if (skb->ip_summed != CHECKSUM_HW)
++ EPRINTK("Trying to TSO send a packet without HW checksum\n");
++
++ tso_start(&state, skb);
++
++ /*
++ * Setup the first payload fragment. If the skb header area
++ * contains exactly the headers and all payload is in the frag
++ * list things are little simpler
++ */
++ if (skb_headlen(skb) == state.p.header_length) {
++ /* Grab the first payload fragment. */
++ BUG_ON(skb_shinfo(skb)->nr_frags < 1);
++ frag_i = 0;
++ f = &skb_shinfo(skb)->frags[frag_i];
++ tso_get_fragment(&state, f->size,
++ page_address(f->page) + f->page_offset);
++ } else {
++ int hl = state.p.header_length;
++ tso_get_fragment(&state, skb_headlen(skb) - hl,
++ skb->data + hl);
++ frag_i = -1;
++ }
++
++ if (tso_start_new_packet(vnic, skb, &state) < 0) {
++ DPRINTK("%s: out of first start-packet memory\n",
++ __FUNCTION__);
++ goto unwind;
++ }
++
++ while (1) {
++ tso_fill_packet_with_fragment(vnic, &state);
++
++ /* Move onto the next fragment? */
++ if (state.ifc.len == 0) {
++ if (++frag_i >= skb_shinfo(skb)->nr_frags)
++ /* End of payload reached. */
++ break;
++ f = &skb_shinfo(skb)->frags[frag_i];
++ tso_get_fragment(&state, f->size,
++ page_address(f->page) +
++ f->page_offset);
++ }
++
++ /* Start a new buffer? */
++ if ((state.output_packets->tso_bufs->length ==
++ NETFRONT_ACCEL_TSO_BUF_LENGTH) &&
++ tso_start_new_buffer(vnic, &state, 0)) {
++ DPRINTK("%s: out of start-buffer memory\n",
++ __FUNCTION__);
++ goto unwind;
++ }
++
++ /* Start at new packet? */
++ if ((state.packet_space == 0 ||
++ ((state.output_packets->tso_bufs_len >=
++ ACCEL_TSO_MAX_BUFFERS) &&
++ (state.output_packets->tso_bufs->length >=
++ NETFRONT_ACCEL_TSO_BUF_LENGTH))) &&
++ tso_start_new_packet(vnic, skb, &state) < 0) {
++ DPRINTK("%s: out of start-packet memory\n",
++ __FUNCTION__);
++ goto unwind;
++ }
++
++ }
++
++ /* Check for space */
++ if (ef_vi_transmit_space(&vnic->vi) < state.buffers) {
++ DPRINTK("%s: Not enough TX space (%d)\n",
++ __FUNCTION__, state.buffers);
++ goto unwind;
++ }
++
++ /*
++ * Store the skb context in the most recent buffer (i.e. the
++ * last buffer that will be sent)
++ */
++ state.output_packets->tso_bufs->buf->skb = skb;
++
++ /* Reverse the list of packets as we construct it on a stack */
++ while (state.output_packets != NULL) {
++ tmp_pkt = state.output_packets;
++ state.output_packets = tmp_pkt->next;
++ tmp_pkt->next = reversed_list;
++ reversed_list = tmp_pkt;
++ }
++
++ /* Pass off to hardware */
++ while (reversed_list != NULL) {
++ tmp_pkt = reversed_list;
++ reversed_list = tmp_pkt->next;
++
++ BUG_ON(tmp_pkt->tso_bufs_len > ACCEL_TSO_MAX_BUFFERS);
++ BUG_ON(tmp_pkt->tso_bufs_len == 0);
++
++ dma_id = tmp_pkt->tso_bufs->buf->buf_id;
++
++ /*
++ * Make an iovec of the buffers in the list, reversing
++ * the buffers as we go as they are constructed on a
++ * stack
++ */
++ tso_buf = tmp_pkt->tso_bufs;
++ for (frag_i = tmp_pkt->tso_bufs_len - 1;
++ frag_i >= 0;
++ frag_i--) {
++ iovecs[frag_i].iov_base = tso_buf->buf->pkt_buff_addr;
++ iovecs[frag_i].iov_len = tso_buf->length;
++ tso_buf = tso_buf->next;
++ }
++
++ rc = ef_vi_transmitv(&vnic->vi, iovecs, tmp_pkt->tso_bufs_len,
++ dma_id);
++ /*
++ * We checked for space already, so it really should
++ * succeed
++ */
++ BUG_ON(rc != 0);
++ }
++
++ /* Track number of tx fastpath stats */
++ vnic->netdev_stats.fastpath_tx_bytes += skb->len;
++ vnic->netdev_stats.fastpath_tx_pkts += state.packets;
++#if NETFRONT_ACCEL_STATS
++ {
++ unsigned n;
++ n = vnic->netdev_stats.fastpath_tx_pkts -
++ vnic->stats.fastpath_tx_completions;
++ if (n > vnic->stats.fastpath_tx_pending_max)
++ vnic->stats.fastpath_tx_pending_max = n;
++ }
++#endif
++
++ return NETFRONT_ACCEL_STATUS_GOOD;
++
++ unwind:
++ tso_unwind(vnic, &state);
++
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.fastpath_tx_busy++);
++
++ return NETFRONT_ACCEL_STATUS_BUSY;
++}
++
++
++
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_tso.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_tso.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_tso.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_tso.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,57 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NETFRONT_ACCEL_TSO_H
++#define NETFRONT_ACCEL_TSO_H
++
++#include "accel_bufs.h"
++
++/* Track the buffers used in each output packet */
++struct netfront_accel_tso_buffer {
++ struct netfront_accel_tso_buffer *next;
++ struct netfront_accel_pkt_desc *buf;
++ unsigned length;
++};
++
++/* Track the output packets formed from each input packet */
++struct netfront_accel_tso_output_packet {
++ struct netfront_accel_tso_output_packet *next;
++ struct netfront_accel_tso_buffer *tso_bufs;
++ unsigned tso_bufs_len;
++};
++
++
++/*
++ * Max available space in a buffer for data once meta-data has taken
++ * its place
++ */
++#define NETFRONT_ACCEL_TSO_BUF_LENGTH \
++ ((PAGE_SIZE / NETFRONT_ACCEL_BUFS_PER_PAGE) \
++ - sizeof(struct netfront_accel_tso_buffer) \
++ - sizeof(struct netfront_accel_tso_output_packet))
++
++int netfront_accel_enqueue_skb_tso(netfront_accel_vnic *vnic,
++ struct sk_buff *skb);
++
++#endif /* NETFRONT_ACCEL_TSO_H */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_vi.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_vi.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_vi.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_vi.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1194 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/if_ether.h>
++#include <linux/ip.h>
++#include <net/checksum.h>
++#include <asm/io.h>
++
++#include "accel.h"
++#include "accel_util.h"
++#include "accel_bufs.h"
++#include "accel_tso.h"
++#include "accel_ssr.h"
++#include "netfront.h"
++
++#include "etherfabric/ef_vi.h"
++
++/*
++ * Max available space in a buffer for data once meta-data has taken
++ * its place
++ */
++#define NETFRONT_ACCEL_TX_BUF_LENGTH \
++ ((PAGE_SIZE / NETFRONT_ACCEL_BUFS_PER_PAGE) \
++ - sizeof(struct netfront_accel_tso_buffer))
++
++#define ACCEL_TX_MAX_BUFFERS (6)
++#define ACCEL_VI_POLL_EVENTS (8)
++
++static
++int netfront_accel_vi_init_fini(netfront_accel_vnic *vnic,
++ struct net_accel_msg_hw *hw_msg)
++{
++ struct ef_vi_nic_type nic_type;
++ struct net_accel_hw_falcon_b *hw_info;
++ void *io_kva, *evq_base, *rx_dma_kva, *tx_dma_kva, *doorbell_kva;
++ u32 *evq_gnts;
++ u32 evq_order;
++ int vi_state_size;
++ u8 vi_data[VI_MAPPINGS_SIZE];
++
++ if (hw_msg == NULL)
++ goto fini;
++
++ /* And create the local macs table lock */
++ spin_lock_init(&vnic->table_lock);
++
++ /* Create fastpath table, initial size 8, key length 8 */
++ if (cuckoo_hash_init(&vnic->fastpath_table, 3, 8)) {
++ EPRINTK("failed to allocate fastpath table\n");
++ goto fail_cuckoo;
++ }
++
++ vnic->hw.falcon.type = hw_msg->type;
++
++ switch (hw_msg->type) {
++ case NET_ACCEL_MSG_HWTYPE_FALCON_A:
++ hw_info = &hw_msg->resources.falcon_a.common;
++ /* Need the extra rptr register page on A1 */
++ io_kva = net_accel_map_iomem_page
++ (vnic->dev, hw_msg->resources.falcon_a.evq_rptr_gnt,
++ &vnic->hw.falcon.evq_rptr_mapping);
++ if (io_kva == NULL) {
++ EPRINTK("%s: evq_rptr permission failed\n", __FUNCTION__);
++ goto evq_rptr_fail;
++ }
++
++ vnic->hw.falcon.evq_rptr = io_kva +
++ (hw_info->evq_rptr & (PAGE_SIZE - 1));
++ break;
++ case NET_ACCEL_MSG_HWTYPE_FALCON_B:
++ hw_info = &hw_msg->resources.falcon_b;
++ break;
++ default:
++ goto bad_type;
++ }
++
++ /**** Event Queue ****/
++
++ /* Map the event queue pages */
++ evq_gnts = hw_info->evq_mem_gnts;
++ evq_order = hw_info->evq_order;
++
++ EPRINTK_ON(hw_info->evq_offs != 0);
++
++ DPRINTK("Will map evq %d pages\n", 1 << evq_order);
++
++ evq_base =
++ net_accel_map_grants_contig(vnic->dev, evq_gnts, 1 << evq_order,
++ &vnic->evq_mapping);
++ if (evq_base == NULL) {
++ EPRINTK("%s: evq_base failed\n", __FUNCTION__);
++ goto evq_fail;
++ }
++
++ /**** Doorbells ****/
++ /* Set up the doorbell mappings. */
++ doorbell_kva =
++ net_accel_map_iomem_page(vnic->dev, hw_info->doorbell_gnt,
++ &vnic->hw.falcon.doorbell_mapping);
++ if (doorbell_kva == NULL) {
++ EPRINTK("%s: doorbell permission failed\n", __FUNCTION__);
++ goto doorbell_fail;
++ }
++ vnic->hw.falcon.doorbell = doorbell_kva;
++
++ /* On Falcon_B we get the rptr from the doorbell page */
++ if (hw_msg->type == NET_ACCEL_MSG_HWTYPE_FALCON_B) {
++ vnic->hw.falcon.evq_rptr =
++ (u32 *)((char *)vnic->hw.falcon.doorbell
++ + hw_info->evq_rptr);
++ }
++
++ /**** DMA Queue ****/
++
++ /* Set up the DMA Queues from the message. */
++ tx_dma_kva = net_accel_map_grants_contig
++ (vnic->dev, &(hw_info->txdmaq_gnt), 1,
++ &vnic->hw.falcon.txdmaq_mapping);
++ if (tx_dma_kva == NULL) {
++ EPRINTK("%s: TX dma failed\n", __FUNCTION__);
++ goto tx_dma_fail;
++ }
++
++ rx_dma_kva = net_accel_map_grants_contig
++ (vnic->dev, &(hw_info->rxdmaq_gnt), 1,
++ &vnic->hw.falcon.rxdmaq_mapping);
++ if (rx_dma_kva == NULL) {
++ EPRINTK("%s: RX dma failed\n", __FUNCTION__);
++ goto rx_dma_fail;
++ }
++
++ /* Full confession */
++ DPRINTK("Mapped H/W"
++ " Tx DMAQ grant %x -> %p\n"
++ " Rx DMAQ grant %x -> %p\n"
++ " EVQ grant %x -> %p\n",
++ hw_info->txdmaq_gnt, tx_dma_kva,
++ hw_info->rxdmaq_gnt, rx_dma_kva,
++ evq_gnts[0], evq_base
++ );
++
++ memset(vi_data, 0, sizeof(vi_data));
++
++ /* TODO BUG11305: convert efhw_arch to ef_vi_arch
++ * e.g.
++ * arch = ef_vi_arch_from_efhw_arch(hw_info->nic_arch);
++ * assert(arch >= 0);
++ * nic_type.arch = arch;
++ */
++ nic_type.arch = (unsigned char)hw_info->nic_arch;
++ nic_type.variant = (char)hw_info->nic_variant;
++ nic_type.revision = (unsigned char)hw_info->nic_revision;
++
++ ef_vi_init_mapping_evq(vi_data, nic_type, hw_info->instance,
++ 1 << (evq_order + PAGE_SHIFT), evq_base,
++ (void *)0xdeadbeef);
++
++ ef_vi_init_mapping_vi(vi_data, nic_type, hw_info->rx_capacity,
++ hw_info->tx_capacity, hw_info->instance,
++ doorbell_kva, rx_dma_kva, tx_dma_kva, 0);
++
++ vi_state_size = ef_vi_calc_state_bytes(hw_info->rx_capacity,
++ hw_info->tx_capacity);
++ vnic->vi_state = (ef_vi_state *)kmalloc(vi_state_size, GFP_KERNEL);
++ if (vnic->vi_state == NULL) {
++ EPRINTK("%s: kmalloc for VI state failed\n", __FUNCTION__);
++ goto vi_state_fail;
++ }
++ ef_vi_init(&vnic->vi, vi_data, vnic->vi_state, &vnic->evq_state, 0);
++
++ ef_eventq_state_init(&vnic->vi);
++
++ ef_vi_state_init(&vnic->vi);
++
++ return 0;
++
++fini:
++ kfree(vnic->vi_state);
++ vnic->vi_state = NULL;
++vi_state_fail:
++ net_accel_unmap_grants_contig(vnic->dev, vnic->hw.falcon.rxdmaq_mapping);
++rx_dma_fail:
++ net_accel_unmap_grants_contig(vnic->dev, vnic->hw.falcon.txdmaq_mapping);
++tx_dma_fail:
++ net_accel_unmap_iomem_page(vnic->dev, vnic->hw.falcon.doorbell_mapping);
++ vnic->hw.falcon.doorbell = NULL;
++doorbell_fail:
++ net_accel_unmap_grants_contig(vnic->dev, vnic->evq_mapping);
++evq_fail:
++ if (vnic->hw.falcon.type == NET_ACCEL_MSG_HWTYPE_FALCON_A)
++ net_accel_unmap_iomem_page(vnic->dev,
++ vnic->hw.falcon.evq_rptr_mapping);
++ vnic->hw.falcon.evq_rptr = NULL;
++evq_rptr_fail:
++bad_type:
++ cuckoo_hash_destroy(&vnic->fastpath_table);
++fail_cuckoo:
++ return -EIO;
++}
++
++
++void netfront_accel_vi_ctor(netfront_accel_vnic *vnic)
++{
++ /* Just mark the VI as uninitialised. */
++ vnic->vi_state = NULL;
++}
++
++
++int netfront_accel_vi_init(netfront_accel_vnic *vnic, struct net_accel_msg_hw *hw_msg)
++{
++ BUG_ON(hw_msg == NULL);
++ return netfront_accel_vi_init_fini(vnic, hw_msg);
++}
++
++
++void netfront_accel_vi_dtor(netfront_accel_vnic *vnic)
++{
++ if (vnic->vi_state != NULL)
++ netfront_accel_vi_init_fini(vnic, NULL);
++}
++
++
++static
++void netfront_accel_vi_post_rx(netfront_accel_vnic *vnic, u16 id,
++ netfront_accel_pkt_desc *buf)
++{
++
++ int idx = vnic->rx_dma_batched;
++
++#if 0
++ VPRINTK("Posting buffer %d (0x%08x) for rx at index %d, space is %d\n",
++ id, buf->pkt_buff_addr, idx, ef_vi_receive_space(&vnic->vi));
++#endif
++ /* Set up a virtual buffer descriptor */
++ ef_vi_receive_init(&vnic->vi, buf->pkt_buff_addr, id,
++ /*rx_bytes=max*/0);
++
++ idx++;
++
++ vnic->rx_dma_level++;
++
++ /*
++ * Only push the descriptor to the card if we've reached the
++ * batch size. Otherwise, the descriptors can sit around for
++ * a while. There will be plenty available.
++ */
++ if (idx >= NETFRONT_ACCEL_RX_DESC_BATCH ||
++ vnic->rx_dma_level < NETFRONT_ACCEL_RX_DESC_BATCH) {
++#if 0
++ VPRINTK("Flushing %d rx descriptors.\n", idx);
++#endif
++
++ /* Push buffer to hardware */
++ ef_vi_receive_push(&vnic->vi);
++
++ idx = 0;
++ }
++
++ vnic->rx_dma_batched = idx;
++}
++
++
++inline
++void netfront_accel_vi_post_rx_or_free(netfront_accel_vnic *vnic, u16 id,
++ netfront_accel_pkt_desc *buf)
++{
++
++ VPRINTK("%s: %d\n", __FUNCTION__, id);
++
++ if (ef_vi_receive_space(&vnic->vi) <= vnic->rx_dma_batched) {
++ VPRINTK("RX space is full\n");
++ netfront_accel_buf_put(vnic->rx_bufs, id);
++ return;
++ }
++
++ VPRINTK("Completed buffer %d is reposted\n", id);
++ netfront_accel_vi_post_rx(vnic, id, buf);
++
++ /*
++ * Let's see if there's any more to be pushed out to the NIC
++ * while we're here
++ */
++ while (ef_vi_receive_space(&vnic->vi) > vnic->rx_dma_batched) {
++ /* Try to allocate a buffer. */
++ buf = netfront_accel_buf_get(vnic->rx_bufs);
++ if (buf == NULL)
++ break;
++
++ /* Add it to the rx dma queue. */
++ netfront_accel_vi_post_rx(vnic, buf->buf_id, buf);
++ }
++}
++
++
++void netfront_accel_vi_add_bufs(netfront_accel_vnic *vnic, int is_rx)
++{
++
++ while (is_rx &&
++ ef_vi_receive_space(&vnic->vi) > vnic->rx_dma_batched) {
++ netfront_accel_pkt_desc *buf;
++
++ VPRINTK("%s: %d\n", __FUNCTION__, vnic->rx_dma_level);
++
++ /* Try to allocate a buffer. */
++ buf = netfront_accel_buf_get(vnic->rx_bufs);
++
++ if (buf == NULL)
++ break;
++
++ /* Add it to the rx dma queue. */
++ netfront_accel_vi_post_rx(vnic, buf->buf_id, buf);
++ }
++
++ VPRINTK("%s: done\n", __FUNCTION__);
++}
++
++
++struct netfront_accel_multi_state {
++ unsigned remaining_len;
++
++ unsigned buffers;
++
++ struct netfront_accel_tso_buffer *output_buffers;
++
++ /* Where we are in the current fragment of the SKB. */
++ struct {
++ /* address of current position */
++ void *addr;
++ /* remaining length */
++ unsigned int len;
++ } ifc; /* == Input Fragment Cursor */
++};
++
++
++static inline void multi_post_start(struct netfront_accel_multi_state *st,
++ struct sk_buff *skb)
++{
++ st->remaining_len = skb->len;
++ st->output_buffers = NULL;
++ st->buffers = 0;
++ st->ifc.len = skb_headlen(skb);
++ st->ifc.addr = skb->data;
++}
++
++static int multi_post_start_new_buffer(netfront_accel_vnic *vnic,
++ struct netfront_accel_multi_state *st)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++ struct netfront_accel_pkt_desc *buf;
++
++ /* Get a mapped packet buffer */
++ buf = netfront_accel_buf_get(vnic->tx_bufs);
++ if (buf == NULL) {
++ DPRINTK("%s: No buffer for TX\n", __FUNCTION__);
++ return -1;
++ }
++
++ /* Store a bit of meta-data at the end */
++ tso_buf = (struct netfront_accel_tso_buffer *)
++ (buf->pkt_kva + NETFRONT_ACCEL_TX_BUF_LENGTH);
++
++ tso_buf->buf = buf;
++
++ tso_buf->length = 0;
++
++ tso_buf->next = st->output_buffers;
++ st->output_buffers = tso_buf;
++ st->buffers++;
++
++ BUG_ON(st->buffers >= ACCEL_TX_MAX_BUFFERS);
++
++ /*
++ * Store the context, set to NULL, last packet buffer will get
++ * non-NULL later
++ */
++ tso_buf->buf->skb = NULL;
++
++ return 0;
++}
++
++
++static void
++multi_post_fill_buffer_with_fragment(netfront_accel_vnic *vnic,
++ struct netfront_accel_multi_state *st)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++ unsigned n, space;
++
++ BUG_ON(st->output_buffers == NULL);
++ tso_buf = st->output_buffers;
++
++ if (st->ifc.len == 0) return;
++ if (tso_buf->length == NETFRONT_ACCEL_TX_BUF_LENGTH) return;
++
++ BUG_ON(tso_buf->length > NETFRONT_ACCEL_TX_BUF_LENGTH);
++
++ space = NETFRONT_ACCEL_TX_BUF_LENGTH - tso_buf->length;
++ n = min(st->ifc.len, space);
++
++ memcpy(tso_buf->buf->pkt_kva + tso_buf->length, st->ifc.addr, n);
++
++ st->remaining_len -= n;
++ st->ifc.len -= n;
++ tso_buf->length += n;
++ st->ifc.addr += n;
++
++ BUG_ON(tso_buf->length > NETFRONT_ACCEL_TX_BUF_LENGTH);
++
++ return;
++}
++
++
++static inline void multi_post_unwind(netfront_accel_vnic *vnic,
++ struct netfront_accel_multi_state *st)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++
++ DPRINTK("%s\n", __FUNCTION__);
++
++ while (st->output_buffers != NULL) {
++ tso_buf = st->output_buffers;
++ st->output_buffers = tso_buf->next;
++ st->buffers--;
++ netfront_accel_buf_put(vnic->tx_bufs, tso_buf->buf->buf_id);
++ }
++ BUG_ON(st->buffers != 0);
++}
++
++
++static enum netfront_accel_post_status
++netfront_accel_enqueue_skb_multi(netfront_accel_vnic *vnic, struct sk_buff *skb)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++ struct netfront_accel_multi_state state;
++ ef_iovec iovecs[ACCEL_TX_MAX_BUFFERS];
++ skb_frag_t *f;
++ int frag_i, rc, dma_id;
++
++ multi_post_start(&state, skb);
++
++ frag_i = -1;
++
++ if (skb->ip_summed == CHECKSUM_HW) {
++ /* Set to zero to encourage falcon to work it out for us */
++ *(u16*)(skb->h.raw + skb->csum) = 0;
++ }
++
++ if (multi_post_start_new_buffer(vnic, &state)) {
++ DPRINTK("%s: out of buffers\n", __FUNCTION__);
++ goto unwind;
++ }
++
++ while (1) {
++ multi_post_fill_buffer_with_fragment(vnic, &state);
++
++ /* Move onto the next fragment? */
++ if (state.ifc.len == 0) {
++ if (++frag_i >= skb_shinfo(skb)->nr_frags)
++ /* End of payload reached. */
++ break;
++ f = &skb_shinfo(skb)->frags[frag_i];
++ state.ifc.len = f->size;
++ state.ifc.addr = page_address(f->page) + f->page_offset;
++ }
++
++ /* Start a new buffer? */
++ if ((state.output_buffers->length ==
++ NETFRONT_ACCEL_TX_BUF_LENGTH) &&
++ multi_post_start_new_buffer(vnic, &state)) {
++ DPRINTK("%s: out of buffers\n", __FUNCTION__);
++ goto unwind;
++ }
++ }
++
++ /* Check for space */
++ if (ef_vi_transmit_space(&vnic->vi) < state.buffers) {
++ DPRINTK("%s: Not enough TX space (%d)\n", __FUNCTION__, state.buffers);
++ goto unwind;
++ }
++
++ /* Store the skb in what will be the last buffer's context */
++ state.output_buffers->buf->skb = skb;
++ /* Remember dma_id of what will be the last buffer */
++ dma_id = state.output_buffers->buf->buf_id;
++
++ /*
++ * Make an iovec of the buffers in the list, reversing the
++ * buffers as we go as they are constructed on a stack
++ */
++ tso_buf = state.output_buffers;
++ for (frag_i = state.buffers-1; frag_i >= 0; frag_i--) {
++ iovecs[frag_i].iov_base = tso_buf->buf->pkt_buff_addr;
++ iovecs[frag_i].iov_len = tso_buf->length;
++ tso_buf = tso_buf->next;
++ }
++
++ rc = ef_vi_transmitv(&vnic->vi, iovecs, state.buffers, dma_id);
++
++ /* Track number of tx fastpath stats */
++ vnic->netdev_stats.fastpath_tx_bytes += skb->len;
++ vnic->netdev_stats.fastpath_tx_pkts ++;
++#if NETFRONT_ACCEL_STATS
++ {
++ u32 n;
++ n = vnic->netdev_stats.fastpath_tx_pkts -
++ (u32)vnic->stats.fastpath_tx_completions;
++ if (n > vnic->stats.fastpath_tx_pending_max)
++ vnic->stats.fastpath_tx_pending_max = n;
++ }
++#endif
++ return NETFRONT_ACCEL_STATUS_GOOD;
++
++unwind:
++ multi_post_unwind(vnic, &state);
++
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.fastpath_tx_busy++);
++
++ return NETFRONT_ACCEL_STATUS_BUSY;
++}
++
++
++static enum netfront_accel_post_status
++netfront_accel_enqueue_skb_single(netfront_accel_vnic *vnic, struct sk_buff *skb)
++{
++ struct netfront_accel_tso_buffer *tso_buf;
++ struct netfront_accel_pkt_desc *buf;
++ u8 *kva;
++ int rc;
++
++ if (ef_vi_transmit_space(&vnic->vi) < 1) {
++ DPRINTK("%s: No TX space\n", __FUNCTION__);
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.fastpath_tx_busy++);
++ return NETFRONT_ACCEL_STATUS_BUSY;
++ }
++
++ buf = netfront_accel_buf_get(vnic->tx_bufs);
++ if (buf == NULL) {
++ DPRINTK("%s: No buffer for TX\n", __FUNCTION__);
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.fastpath_tx_busy++);
++ return NETFRONT_ACCEL_STATUS_BUSY;
++ }
++
++ /* Track number of tx fastpath stats */
++ vnic->netdev_stats.fastpath_tx_pkts++;
++ vnic->netdev_stats.fastpath_tx_bytes += skb->len;
++
++#if NETFRONT_ACCEL_STATS
++ {
++ u32 n;
++ n = vnic->netdev_stats.fastpath_tx_pkts -
++ (u32)vnic->stats.fastpath_tx_completions;
++ if (n > vnic->stats.fastpath_tx_pending_max)
++ vnic->stats.fastpath_tx_pending_max = n;
++ }
++#endif
++
++ /* Store the context */
++ buf->skb = skb;
++
++ kva = buf->pkt_kva;
++
++ if (skb->ip_summed == CHECKSUM_HW) {
++ /* Set to zero to encourage falcon to work it out for us */
++ *(u16*)(skb->h.raw + skb->csum) = 0;
++ }
++ NETFRONT_ACCEL_PKTBUFF_FOR_EACH_FRAGMENT
++ (skb, idx, frag_data, frag_len, {
++ /* Copy in payload */
++ VPRINTK("*** Copying %d bytes to %p\n", frag_len, kva);
++ memcpy(kva, frag_data, frag_len);
++ kva += frag_len;
++ });
++
++ VPRINTK("%s: id %d pkt %p kva %p buff_addr 0x%08x\n", __FUNCTION__,
++ buf->buf_id, buf, buf->pkt_kva, buf->pkt_buff_addr);
++
++
++ /* Set up the TSO meta-data for a single buffer/packet */
++ tso_buf = (struct netfront_accel_tso_buffer *)
++ (buf->pkt_kva + NETFRONT_ACCEL_TX_BUF_LENGTH);
++ tso_buf->next = NULL;
++ tso_buf->buf = buf;
++ tso_buf->length = skb->len;
++
++ rc = ef_vi_transmit(&vnic->vi, buf->pkt_buff_addr, skb->len,
++ buf->buf_id);
++ /* We checked for space already, so it really should succeed */
++ BUG_ON(rc != 0);
++
++ return NETFRONT_ACCEL_STATUS_GOOD;
++}
++
++
++enum netfront_accel_post_status
++netfront_accel_vi_tx_post(netfront_accel_vnic *vnic, struct sk_buff *skb)
++{
++ struct ethhdr *pkt_eth_hdr;
++ struct iphdr *pkt_ipv4_hdr;
++ int value, try_fastpath;
++
++ /*
++ * This assumes that the data field points to the dest mac
++ * address.
++ */
++ cuckoo_hash_mac_key key = cuckoo_mac_to_key(skb->data);
++
++ /*
++ * NB very important that all things that could return "CANT"
++ * are tested before things that return "BUSY" as if it it
++ * returns "BUSY" it is assumed that it won't return "CANT"
++ * next time it is tried
++ */
++
++ /*
++ * Do a fastpath send if fast path table lookup returns true.
++ * We do this without the table lock and so may get the wrong
++ * answer, but current opinion is that's not a big problem
++ */
++ try_fastpath = cuckoo_hash_lookup(&vnic->fastpath_table,
++ (cuckoo_hash_key *)(&key), &value);
++
++ if (!try_fastpath) {
++ VPRINTK("try fast path false for mac: " MAC_FMT "\n",
++ MAC_ARG(skb->data));
++
++ return NETFRONT_ACCEL_STATUS_CANT;
++ }
++
++ /* Check to see if the packet can be sent. */
++ if (skb_headlen(skb) < sizeof(*pkt_eth_hdr) + sizeof(*pkt_ipv4_hdr)) {
++ EPRINTK("%s: Packet header is too small\n", __FUNCTION__);
++ return NETFRONT_ACCEL_STATUS_CANT;
++ }
++
++ pkt_eth_hdr = (void*)skb->data;
++ pkt_ipv4_hdr = (void*)(pkt_eth_hdr+1);
++
++ if (be16_to_cpu(pkt_eth_hdr->h_proto) != ETH_P_IP) {
++ DPRINTK("%s: Packet is not IPV4 (ether_type=0x%04x)\n", __FUNCTION__,
++ be16_to_cpu(pkt_eth_hdr->h_proto));
++ return NETFRONT_ACCEL_STATUS_CANT;
++ }
++
++ if (pkt_ipv4_hdr->protocol != IPPROTO_TCP &&
++ pkt_ipv4_hdr->protocol != IPPROTO_UDP) {
++ DPRINTK("%s: Packet is not TCP/UDP (ip_protocol=0x%02x)\n",
++ __FUNCTION__, pkt_ipv4_hdr->protocol);
++ return NETFRONT_ACCEL_STATUS_CANT;
++ }
++
++ VPRINTK("%s: %d bytes, gso %d\n", __FUNCTION__, skb->len,
++ skb_shinfo(skb)->gso_size);
++
++ if (skb_shinfo(skb)->gso_size) {
++ return netfront_accel_enqueue_skb_tso(vnic, skb);
++ }
++
++ if (skb->len <= NETFRONT_ACCEL_TX_BUF_LENGTH) {
++ return netfront_accel_enqueue_skb_single(vnic, skb);
++ }
++
++ return netfront_accel_enqueue_skb_multi(vnic, skb);
++}
++
++
++/*
++ * Copy the data to required end destination. NB. len is the total new
++ * length of the socket buffer, not the amount of data to copy
++ */
++inline
++int ef_vnic_copy_to_skb(netfront_accel_vnic *vnic, struct sk_buff *skb,
++ struct netfront_accel_pkt_desc *buf, int len)
++{
++ int i, extra = len - skb->len;
++ char c;
++ int pkt_stride = vnic->rx_pkt_stride;
++ int skb_stride = vnic->rx_skb_stride;
++ char *skb_start;
++
++ /*
++ * This pulls stuff into the cache - have seen performance
++ * benefit in this, but disabled by default
++ */
++ skb_start = skb->data;
++ if (pkt_stride) {
++ for (i = 0; i < len; i += pkt_stride) {
++ c += ((volatile char*)(buf->pkt_kva))[i];
++ }
++ }
++ if (skb_stride) {
++ for (i = skb->len; i < len ; i += skb_stride) {
++ c += ((volatile char*)(skb_start))[i];
++ }
++ }
++
++ if (skb_tailroom(skb) >= extra) {
++ memcpy(skb_put(skb, extra), buf->pkt_kva, extra);
++ return 0;
++ }
++
++ return -ENOSPC;
++}
++
++
++static void discard_jumbo_state(netfront_accel_vnic *vnic)
++{
++
++ if (vnic->jumbo_state.skb != NULL) {
++ dev_kfree_skb_any(vnic->jumbo_state.skb);
++
++ vnic->jumbo_state.skb = NULL;
++ }
++ vnic->jumbo_state.in_progress = 0;
++}
++
++
++static void netfront_accel_vi_rx_complete(netfront_accel_vnic *vnic,
++ struct sk_buff *skb)
++{
++ cuckoo_hash_mac_key key;
++ unsigned long flags;
++ int value;
++ struct net_device *net_dev;
++
++
++ key = cuckoo_mac_to_key(skb->data + ETH_ALEN);
++
++ /*
++ * If this is a MAC address that we want to do fast path TX
++ * to, and we don't already, add it to the fastpath table.
++ * The initial lookup is done without the table lock and so
++ * may get the wrong answer, but current opinion is that's not
++ * a big problem
++ */
++ if (is_valid_ether_addr(skb->data + ETH_ALEN) &&
++ !cuckoo_hash_lookup(&vnic->fastpath_table, (cuckoo_hash_key *)&key,
++ &value)) {
++ spin_lock_irqsave(&vnic->table_lock, flags);
++
++ cuckoo_hash_add_check(&vnic->fastpath_table,
++ (cuckoo_hash_key *)&key,
++ 1, 1);
++
++ spin_unlock_irqrestore(&vnic->table_lock, flags);
++ }
++
++ if (compare_ether_addr(skb->data, vnic->mac)) {
++ struct iphdr *ip = (struct iphdr *)(skb->data + ETH_HLEN);
++ u16 port;
++
++ DPRINTK("%s: saw wrong MAC address " MAC_FMT "\n",
++ __FUNCTION__, MAC_ARG(skb->data));
++
++ if (ip->protocol == IPPROTO_TCP) {
++ struct tcphdr *tcp = (struct tcphdr *)
++ ((char *)ip + 4 * ip->ihl);
++ port = tcp->dest;
++ } else {
++ struct udphdr *udp = (struct udphdr *)
++ ((char *)ip + 4 * ip->ihl);
++ EPRINTK_ON(ip->protocol != IPPROTO_UDP);
++ port = udp->dest;
++ }
++
++ netfront_accel_msg_tx_fastpath(vnic, skb->data,
++ ip->daddr, port,
++ ip->protocol);
++ }
++
++ net_dev = vnic->net_dev;
++ skb->dev = net_dev;
++ skb->protocol = eth_type_trans(skb, net_dev);
++ /* CHECKSUM_UNNECESSARY as hardware has done it already */
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ if (!netfront_accel_ssr_skb(vnic, &vnic->ssr_state, skb))
++ netif_receive_skb(skb);
++}
++
++
++static int netfront_accel_vi_poll_process_rx(netfront_accel_vnic *vnic,
++ ef_event *ev)
++{
++ struct netfront_accel_bufinfo *bufinfo = vnic->rx_bufs;
++ struct netfront_accel_pkt_desc *buf = NULL;
++ struct sk_buff *skb;
++ int id, len, sop = 0, cont = 0;
++
++ VPRINTK("Rx event.\n");
++ /*
++ * Complete the receive operation, and get the request id of
++ * the buffer
++ */
++ id = ef_vi_receive_done(&vnic->vi, ev);
++
++ if (id < 0 || id >= bufinfo->npages*NETFRONT_ACCEL_BUFS_PER_PAGE) {
++ EPRINTK("Rx packet %d is invalid\n", id);
++ /* Carry on round the loop if more events */
++ goto bad_packet;
++ }
++ /* Get our buffer descriptor */
++ buf = netfront_accel_buf_find(bufinfo, id);
++
++ len = EF_EVENT_RX_BYTES(*ev);
++
++ /* An RX buffer has been removed from the DMA ring. */
++ vnic->rx_dma_level--;
++
++ if (EF_EVENT_TYPE(*ev) == EF_EVENT_TYPE_RX) {
++ sop = EF_EVENT_RX_SOP(*ev);
++ cont = EF_EVENT_RX_CONT(*ev);
++
++ skb = vnic->jumbo_state.skb;
++
++ VPRINTK("Rx packet %d: %d bytes so far; sop %d; cont %d\n",
++ id, len, sop, cont);
++
++ if (sop) {
++ if (!vnic->jumbo_state.in_progress) {
++ vnic->jumbo_state.in_progress = 1;
++ BUG_ON(vnic->jumbo_state.skb != NULL);
++ } else {
++ /*
++ * This fragment shows a missing tail in
++ * previous one, but is itself possibly OK
++ */
++ DPRINTK("sop and in_progress => no tail\n");
++
++ /* Release the socket buffer we already had */
++ discard_jumbo_state(vnic);
++
++ /* Now start processing this fragment */
++ vnic->jumbo_state.in_progress = 1;
++ skb = NULL;
++ }
++ } else if (!vnic->jumbo_state.in_progress) {
++ DPRINTK("!sop and !in_progress => missing head\n");
++ goto missing_head;
++ }
++
++ if (!cont) {
++ /* Update state for next time */
++ vnic->jumbo_state.in_progress = 0;
++ vnic->jumbo_state.skb = NULL;
++ } else if (!vnic->jumbo_state.in_progress) {
++ DPRINTK("cont and !in_progress => missing head\n");
++ goto missing_head;
++ }
++
++ if (skb == NULL) {
++ BUG_ON(!sop);
++
++ if (!cont)
++ skb = alloc_skb(len+NET_IP_ALIGN, GFP_ATOMIC);
++ else
++ skb = alloc_skb(vnic->net_dev->mtu+NET_IP_ALIGN,
++ GFP_ATOMIC);
++
++ if (skb == NULL) {
++ DPRINTK("%s: Couldn't get an rx skb.\n",
++ __FUNCTION__);
++ netfront_accel_vi_post_rx_or_free(vnic, (u16)id, buf);
++ /*
++ * Dropping this fragment means we
++ * should discard the rest too
++ */
++ discard_jumbo_state(vnic);
++
++ /* Carry on round the loop if more events */
++ return 0;
++ }
++
++ }
++
++ /* Copy the data to required end destination */
++ if (ef_vnic_copy_to_skb(vnic, skb, buf, len) != 0) {
++ /*
++ * No space in the skb - suggests > MTU packet
++ * received
++ */
++ EPRINTK("%s: Rx packet too large (%d)\n",
++ __FUNCTION__, len);
++ netfront_accel_vi_post_rx_or_free(vnic, (u16)id, buf);
++ discard_jumbo_state(vnic);
++ return 0;
++ }
++
++ /* Put the buffer back in the DMA queue. */
++ netfront_accel_vi_post_rx_or_free(vnic, (u16)id, buf);
++
++ if (cont) {
++ vnic->jumbo_state.skb = skb;
++
++ return 0;
++ } else {
++ /* Track number of rx fastpath packets */
++ vnic->netdev_stats.fastpath_rx_pkts++;
++ vnic->netdev_stats.fastpath_rx_bytes += len;
++
++ netfront_accel_vi_rx_complete(vnic, skb);
++
++ return 1;
++ }
++ } else {
++ BUG_ON(EF_EVENT_TYPE(*ev) != EF_EVENT_TYPE_RX_DISCARD);
++
++ if (EF_EVENT_RX_DISCARD_TYPE(*ev)
++ == EF_EVENT_RX_DISCARD_TRUNC) {
++ DPRINTK("%s: " EF_EVENT_FMT
++ " buffer %d FRM_TRUNC q_id %d\n",
++ __FUNCTION__, EF_EVENT_PRI_ARG(*ev), id,
++ EF_EVENT_RX_DISCARD_Q_ID(*ev) );
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.fastpath_frm_trunc);
++ } else if (EF_EVENT_RX_DISCARD_TYPE(*ev)
++ == EF_EVENT_RX_DISCARD_OTHER) {
++ DPRINTK("%s: " EF_EVENT_FMT
++ " buffer %d RX_DISCARD_OTHER q_id %d\n",
++ __FUNCTION__, EF_EVENT_PRI_ARG(*ev), id,
++ EF_EVENT_RX_DISCARD_Q_ID(*ev) );
++ /*
++ * Probably tail of packet for which error has
++ * already been logged, so don't count in
++ * stats
++ */
++ } else {
++ EPRINTK("%s: " EF_EVENT_FMT
++ " buffer %d rx discard type %d q_id %d\n",
++ __FUNCTION__, EF_EVENT_PRI_ARG(*ev), id,
++ EF_EVENT_RX_DISCARD_TYPE(*ev),
++ EF_EVENT_RX_DISCARD_Q_ID(*ev) );
++ NETFRONT_ACCEL_STATS_OP(++vnic->stats.bad_event_count);
++ }
++ }
++
++ /* discard type drops through here */
++
++bad_packet:
++ /* Release the socket buffer we already had */
++ discard_jumbo_state(vnic);
++
++missing_head:
++ BUG_ON(vnic->jumbo_state.in_progress != 0);
++ BUG_ON(vnic->jumbo_state.skb != NULL);
++
++ if (id >= 0 && id < bufinfo->npages*NETFRONT_ACCEL_BUFS_PER_PAGE)
++ /* Put the buffer back in the DMA queue. */
++ netfront_accel_vi_post_rx_or_free(vnic, (u16)id, buf);
++
++ vnic->netdev_stats.fastpath_rx_errors++;
++
++ DPRINTK("%s experienced bad packet/missing fragment error: %d \n",
++ __FUNCTION__, ev->rx.flags);
++
++ return 0;
++}
++
++
++static void netfront_accel_vi_not_busy(netfront_accel_vnic *vnic)
++{
++ struct netfront_info *np = ((struct netfront_info *)
++ netdev_priv(vnic->net_dev));
++ struct sk_buff *skb;
++ int handled;
++ unsigned long flags;
++
++ /*
++ * TODO if we could safely check tx_skb == NULL and return
++ * early without taking the lock, that would obviously help
++ * performance
++ */
++
++ /* Take the netfront lock which protects tx_skb. */
++ spin_lock_irqsave(&np->tx_lock, flags);
++ if (vnic->tx_skb != NULL) {
++ DPRINTK("%s trying to send spare buffer\n", __FUNCTION__);
++
++ skb = vnic->tx_skb;
++ vnic->tx_skb = NULL;
++
++ spin_unlock_irqrestore(&np->tx_lock, flags);
++
++ handled = netfront_accel_vi_tx_post(vnic, skb);
++
++ spin_lock_irqsave(&np->tx_lock, flags);
++
++ if (handled != NETFRONT_ACCEL_STATUS_BUSY) {
++ DPRINTK("%s restarting tx\n", __FUNCTION__);
++ if (netfront_check_queue_ready(vnic->net_dev)) {
++ netif_wake_queue(vnic->net_dev);
++ NETFRONT_ACCEL_STATS_OP
++ (vnic->stats.queue_wakes++);
++ }
++ } else {
++ vnic->tx_skb = skb;
++ }
++
++ /*
++ * Should never get a CANT, as it checks that before
++ * deciding it was BUSY first time round
++ */
++ BUG_ON(handled == NETFRONT_ACCEL_STATUS_CANT);
++ }
++ spin_unlock_irqrestore(&np->tx_lock, flags);
++}
++
++
++static void netfront_accel_vi_tx_complete(netfront_accel_vnic *vnic,
++ struct netfront_accel_tso_buffer *tso_buf,
++ int is_last)
++{
++ struct netfront_accel_tso_buffer *next;
++
++ /*
++ * We get a single completion for every call to
++ * ef_vi_transmitv so handle any other buffers which are part
++ * of the same packet
++ */
++ while (tso_buf != NULL) {
++ if (tso_buf->buf->skb != NULL) {
++ dev_kfree_skb_any(tso_buf->buf->skb);
++ tso_buf->buf->skb = NULL;
++ }
++
++ next = tso_buf->next;
++
++ netfront_accel_buf_put(vnic->tx_bufs, tso_buf->buf->buf_id);
++
++ tso_buf = next;
++ }
++
++ /*
++ * If this was the last one in the batch, we try and send any
++ * pending tx_skb. There should now be buffers and
++ * descriptors
++ */
++ if (is_last)
++ netfront_accel_vi_not_busy(vnic);
++}
++
++
++static void netfront_accel_vi_poll_process_tx(netfront_accel_vnic *vnic,
++ ef_event *ev)
++{
++ struct netfront_accel_pkt_desc *buf;
++ struct netfront_accel_tso_buffer *tso_buf;
++ ef_request_id ids[EF_VI_TRANSMIT_BATCH];
++ int i, n_ids;
++ unsigned long flags;
++
++ /* Get the request ids for this tx completion event. */
++ n_ids = ef_vi_transmit_unbundle(&vnic->vi, ev, ids);
++
++ /* Take the tx buffer spin lock and hold for the duration */
++ spin_lock_irqsave(&vnic->tx_lock, flags);
++
++ for (i = 0; i < n_ids; ++i) {
++ VPRINTK("Tx packet %d complete\n", ids[i]);
++ buf = netfront_accel_buf_find(vnic->tx_bufs, ids[i]);
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.fastpath_tx_completions++);
++
++ tso_buf = (struct netfront_accel_tso_buffer *)
++ (buf->pkt_kva + NETFRONT_ACCEL_TX_BUF_LENGTH);
++ BUG_ON(tso_buf->buf != buf);
++
++ netfront_accel_vi_tx_complete(vnic, tso_buf, i == (n_ids-1));
++ }
++
++ spin_unlock_irqrestore(&vnic->tx_lock, flags);
++}
++
++
++int netfront_accel_vi_poll(netfront_accel_vnic *vnic, int rx_packets)
++{
++ ef_event ev[ACCEL_VI_POLL_EVENTS];
++ int rx_remain = rx_packets, rc, events, i;
++#if NETFRONT_ACCEL_STATS
++ int n_evs_polled = 0, rx_evs_polled = 0, tx_evs_polled = 0;
++#endif
++ BUG_ON(rx_packets <= 0);
++
++ events = ef_eventq_poll(&vnic->vi, ev,
++ min(rx_remain, ACCEL_VI_POLL_EVENTS));
++ i = 0;
++ NETFRONT_ACCEL_STATS_OP(n_evs_polled += events);
++
++ VPRINTK("%s: %d events\n", __FUNCTION__, events);
++
++ /* Loop over each event */
++ while (events) {
++ VPRINTK("%s: Event "EF_EVENT_FMT", index %lu\n", __FUNCTION__,
++ EF_EVENT_PRI_ARG(ev[i]),
++ (unsigned long)(vnic->vi.evq_state->evq_ptr));
++
++ if ((EF_EVENT_TYPE(ev[i]) == EF_EVENT_TYPE_RX) ||
++ (EF_EVENT_TYPE(ev[i]) == EF_EVENT_TYPE_RX_DISCARD)) {
++ rc = netfront_accel_vi_poll_process_rx(vnic, &ev[i]);
++ rx_remain -= rc;
++ BUG_ON(rx_remain < 0);
++ NETFRONT_ACCEL_STATS_OP(rx_evs_polled++);
++ } else if (EF_EVENT_TYPE(ev[i]) == EF_EVENT_TYPE_TX) {
++ netfront_accel_vi_poll_process_tx(vnic, &ev[i]);
++ NETFRONT_ACCEL_STATS_OP(tx_evs_polled++);
++ } else if (EF_EVENT_TYPE(ev[i]) ==
++ EF_EVENT_TYPE_RX_NO_DESC_TRUNC) {
++ DPRINTK("%s: RX_NO_DESC_TRUNC " EF_EVENT_FMT "\n",
++ __FUNCTION__, EF_EVENT_PRI_ARG(ev[i]));
++ discard_jumbo_state(vnic);
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.rx_no_desc_trunc++);
++ } else {
++ EPRINTK("Unexpected event " EF_EVENT_FMT "\n",
++ EF_EVENT_PRI_ARG(ev[i]));
++ NETFRONT_ACCEL_STATS_OP(vnic->stats.bad_event_count++);
++ }
++
++ i++;
++
++ /* Carry on round the loop if more events and more space */
++ if (i == events) {
++ if (rx_remain == 0)
++ break;
++
++ events = ef_eventq_poll(&vnic->vi, ev,
++ min(rx_remain,
++ ACCEL_VI_POLL_EVENTS));
++ i = 0;
++ NETFRONT_ACCEL_STATS_OP(n_evs_polled += events);
++ }
++ }
++
++#if NETFRONT_ACCEL_STATS
++ vnic->stats.event_count += n_evs_polled;
++ vnic->stats.event_count_since_irq += n_evs_polled;
++ if (n_evs_polled > vnic->stats.events_per_poll_max)
++ vnic->stats.events_per_poll_max = n_evs_polled;
++ if (rx_evs_polled > vnic->stats.events_per_poll_rx_max)
++ vnic->stats.events_per_poll_rx_max = rx_evs_polled;
++ if (tx_evs_polled > vnic->stats.events_per_poll_tx_max)
++ vnic->stats.events_per_poll_tx_max = tx_evs_polled;
++#endif
++
++ return rx_packets - rx_remain;
++}
++
++
++int netfront_accel_vi_enable_interrupts(netfront_accel_vnic *vnic)
++{
++ u32 sw_evq_ptr;
++
++ VPRINTK("%s: checking for event on %p\n", __FUNCTION__, &vnic->vi.evq_state);
++
++ BUG_ON(vnic == NULL);
++ BUG_ON(vnic->vi.evq_state == NULL);
++
++ /* Do a quick check for an event. */
++ if (ef_eventq_has_event(&vnic->vi)) {
++ VPRINTK("%s: found event\n", __FUNCTION__);
++ return 0;
++ }
++
++ VPRINTK("evq_ptr=0x%08x evq_mask=0x%08x\n",
++ vnic->evq_state.evq_ptr, vnic->vi.evq_mask);
++
++ /* Request a wakeup from the hardware. */
++ sw_evq_ptr = vnic->evq_state.evq_ptr & vnic->vi.evq_mask;
++
++ BUG_ON(vnic->hw.falcon.evq_rptr == NULL);
++
++ VPRINTK("Requesting wakeup at 0x%08x, rptr %p\n", sw_evq_ptr,
++ vnic->hw.falcon.evq_rptr);
++ *(volatile u32 *)(vnic->hw.falcon.evq_rptr) = (sw_evq_ptr >> 3);
++
++ return 1;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/accel_xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_xenbus.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/accel_xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/accel_xenbus.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,776 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/stddef.h>
++#include <linux/errno.h>
++
++#include <xen/xenbus.h>
++#include <xen/evtchn.h>
++#include <xen/gnttab.h>
++
++#include "accel.h"
++#include "accel_util.h"
++#include "accel_msg_iface.h"
++#include "accel_bufs.h"
++#include "accel_ssr.h"
++/* drivers/xen/netfront/netfront.h */
++#include "netfront.h"
++
++void netfront_accel_set_closing(netfront_accel_vnic *vnic)
++{
++
++ vnic->frontend_state = XenbusStateClosing;
++ net_accel_update_state(vnic->dev, XenbusStateClosing);
++}
++
++
++static void mac_address_change(struct xenbus_watch *watch,
++ const char **vec, unsigned int len)
++{
++ netfront_accel_vnic *vnic;
++ struct xenbus_device *dev;
++ int rc;
++
++ DPRINTK("%s\n", __FUNCTION__);
++
++ vnic = container_of(watch, netfront_accel_vnic,
++ mac_address_watch);
++ dev = vnic->dev;
++
++ rc = net_accel_xen_net_read_mac(dev, vnic->mac);
++
++ if (rc != 0)
++ EPRINTK("%s: failed to read mac (%d)\n", __FUNCTION__, rc);
++}
++
++
++static int setup_mac_address_watch(struct xenbus_device *dev,
++ netfront_accel_vnic *vnic)
++{
++ int err;
++
++ DPRINTK("Setting watch on %s/%s\n", dev->nodename, "mac");
++
++ err = xenbus_watch_path2(dev, dev->nodename, "mac",
++ &vnic->mac_address_watch,
++ mac_address_change);
++ if (err) {
++ EPRINTK("%s: Failed to register xenbus watch: %d\n",
++ __FUNCTION__, err);
++ goto fail;
++ }
++
++ return 0;
++ fail:
++ vnic->mac_address_watch.node = NULL;
++ return err;
++}
++
++
++/* Grant access to some pages and publish through xenbus */
++static int make_named_grant(struct xenbus_device *dev, void *page,
++ const char *name, grant_ref_t *gnt_ref)
++{
++ struct xenbus_transaction tr;
++ int err;
++ grant_ref_t gnt;
++
++ gnt = net_accel_grant_page(dev, virt_to_mfn(page), 0);
++ if (gnt < 0)
++ return gnt;
++
++ do {
++ err = xenbus_transaction_start(&tr);
++ if (err != 0) {
++ EPRINTK("%s: transaction start failed %d\n",
++ __FUNCTION__, err);
++ return err;
++ }
++ err = xenbus_printf(tr, dev->nodename, name, "%d", gnt);
++ if (err != 0) {
++ EPRINTK("%s: xenbus_printf failed %d\n", __FUNCTION__,
++ err);
++ xenbus_transaction_end(tr, 1);
++ return err;
++ }
++ err = xenbus_transaction_end(tr, 0);
++ } while (err == -EAGAIN);
++
++ if (err != 0) {
++ EPRINTK("%s: transaction end failed %d\n", __FUNCTION__, err);
++ return err;
++ }
++
++ *gnt_ref = gnt;
++
++ return 0;
++}
++
++
++static int remove_named_grant(struct xenbus_device *dev,
++ const char *name, grant_ref_t gnt_ref)
++{
++ struct xenbus_transaction tr;
++ int err;
++
++ net_accel_ungrant_page(gnt_ref);
++
++ do {
++ err = xenbus_transaction_start(&tr);
++ if (err != 0) {
++ EPRINTK("%s: transaction start failed %d\n",
++ __FUNCTION__, err);
++ return err;
++ }
++ err = xenbus_rm(tr, dev->nodename, name);
++ if (err != 0) {
++ EPRINTK("%s: xenbus_rm failed %d\n", __FUNCTION__,
++ err);
++ xenbus_transaction_end(tr, 1);
++ return err;
++ }
++ err = xenbus_transaction_end(tr, 0);
++ } while (err == -EAGAIN);
++
++ if (err != 0) {
++ EPRINTK("%s: transaction end failed %d\n", __FUNCTION__, err);
++ return err;
++ }
++
++ return 0;
++}
++
++
++static
++netfront_accel_vnic *netfront_accel_vnic_ctor(struct net_device *net_dev,
++ struct xenbus_device *dev)
++{
++ struct netfront_info *np =
++ (struct netfront_info *)netdev_priv(net_dev);
++ netfront_accel_vnic *vnic;
++ int err;
++
++ /*
++ * A bug in earlier versions of Xen accel plugin system meant
++ * you could be probed twice for the same device on suspend
++ * cancel. Be tolerant of that.
++ */
++ if (np->accel_priv != NULL)
++ return ERR_PTR(-EALREADY);
++
++ /* Alloc mem for state */
++ vnic = kzalloc(sizeof(netfront_accel_vnic), GFP_KERNEL);
++ if (vnic == NULL) {
++ EPRINTK("%s: no memory for vnic state\n", __FUNCTION__);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ spin_lock_init(&vnic->tx_lock);
++
++ mutex_init(&vnic->vnic_mutex);
++ mutex_lock(&vnic->vnic_mutex);
++
++ /* Store so state can be retrieved from device */
++ BUG_ON(np->accel_priv != NULL);
++ np->accel_priv = vnic;
++ vnic->dev = dev;
++ vnic->net_dev = net_dev;
++ spin_lock_init(&vnic->irq_enabled_lock);
++ netfront_accel_ssr_init(&vnic->ssr_state);
++
++ init_waitqueue_head(&vnic->state_wait_queue);
++ vnic->backend_state = XenbusStateUnknown;
++ vnic->frontend_state = XenbusStateClosed;
++ vnic->removing = 0;
++ vnic->domU_state_is_setup = 0;
++ vnic->dom0_state_is_setup = 0;
++ vnic->poll_enabled = 0;
++ vnic->tx_enabled = 0;
++ vnic->tx_skb = NULL;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ INIT_WORK(&vnic->msg_from_bend, netfront_accel_msg_from_bend);
++#else
++ INIT_WORK(&vnic->msg_from_bend, netfront_accel_msg_from_bend, vnic);
++#endif
++
++ netfront_accel_debugfs_create(vnic);
++
++ mutex_unlock(&vnic->vnic_mutex);
++
++ err = net_accel_xen_net_read_mac(dev, vnic->mac);
++ if (err)
++ goto fail_mac;
++
++ /* Setup a watch on the frontend's MAC address */
++ err = setup_mac_address_watch(dev, vnic);
++ if (err)
++ goto fail_mac;
++
++ return vnic;
++
++fail_mac:
++
++ mutex_lock(&vnic->vnic_mutex);
++
++ netfront_accel_debugfs_remove(vnic);
++
++ netfront_accel_ssr_fini(vnic, &vnic->ssr_state);
++
++ EPRINTK_ON(vnic->tx_skb != NULL);
++
++ vnic->frontend_state = XenbusStateUnknown;
++ net_accel_update_state(dev, XenbusStateUnknown);
++
++ mutex_unlock(&vnic->vnic_mutex);
++
++ np->accel_priv = NULL;
++ kfree(vnic);
++
++ return ERR_PTR(err);
++}
++
++
++static void netfront_accel_vnic_dtor(netfront_accel_vnic *vnic)
++{
++ struct net_device *net_dev = vnic->net_dev;
++ struct netfront_info *np =
++ (struct netfront_info *)netdev_priv(net_dev);
++
++ /*
++ * Now we don't hold the lock any more it is safe to remove
++ * this watch and synchonrise with the completion of
++ * watches
++ */
++ DPRINTK("%s: unregistering xenbus mac watch\n", __FUNCTION__);
++ unregister_xenbus_watch(&vnic->mac_address_watch);
++ kfree(vnic->mac_address_watch.node);
++
++ flush_workqueue(netfront_accel_workqueue);
++
++ mutex_lock(&vnic->vnic_mutex);
++
++ netfront_accel_debugfs_remove(vnic);
++
++ netfront_accel_ssr_fini(vnic, &vnic->ssr_state);
++
++ EPRINTK_ON(vnic->tx_skb != NULL);
++
++ vnic->frontend_state = XenbusStateUnknown;
++ net_accel_update_state(vnic->dev, XenbusStateUnknown);
++
++ mutex_unlock(&vnic->vnic_mutex);
++
++ np->accel_priv = NULL;
++ kfree(vnic);
++}
++
++
++static int vnic_setup_domU_shared_state(struct xenbus_device *dev,
++ netfront_accel_vnic *vnic)
++{
++ struct xenbus_transaction tr;
++ int err;
++ int msgs_per_queue;
++
++
++ DPRINTK("Setting up domU shared state.\n");
++
++ msgs_per_queue = (PAGE_SIZE/2) / sizeof(struct net_accel_msg);
++
++ /* Allocate buffer state */
++ vnic->tx_bufs = netfront_accel_init_bufs(&vnic->tx_lock);
++ if (vnic->tx_bufs == NULL) {
++ err = -ENOMEM;
++ EPRINTK("%s: Failed to allocate tx buffers\n", __FUNCTION__);
++ goto fail_tx_bufs;
++ }
++
++ vnic->rx_bufs = netfront_accel_init_bufs(NULL);
++ if (vnic->rx_bufs == NULL) {
++ err = -ENOMEM;
++ EPRINTK("%s: Failed to allocate rx buffers\n", __FUNCTION__);
++ goto fail_rx_bufs;
++ }
++
++ /*
++ * This allocates two pages, one for the shared page and one
++ * for the message queue.
++ */
++ vnic->shared_page = (struct net_accel_shared_page *)
++ __get_free_pages(GFP_KERNEL, 1);
++ if (vnic->shared_page == NULL) {
++ EPRINTK("%s: no memory for shared pages\n", __FUNCTION__);
++ err = -ENOMEM;
++ goto fail_shared_page;
++ }
++
++ net_accel_msg_init_queue
++ (&vnic->from_dom0, &vnic->shared_page->queue0,
++ (struct net_accel_msg *)((u8*)vnic->shared_page + PAGE_SIZE),
++ msgs_per_queue);
++
++ net_accel_msg_init_queue
++ (&vnic->to_dom0, &vnic->shared_page->queue1,
++ (struct net_accel_msg *)((u8*)vnic->shared_page +
++ (3 * PAGE_SIZE / 2)),
++ msgs_per_queue);
++
++ vnic->msg_state = NETFRONT_ACCEL_MSG_NONE;
++
++ err = make_named_grant(dev, vnic->shared_page, "accel-ctrl-page",
++ &vnic->ctrl_page_gnt);
++ if (err) {
++ EPRINTK("couldn't make ctrl-page named grant\n");
++ goto fail_ctrl_page_grant;
++ }
++
++ err = make_named_grant(dev, (u8*)vnic->shared_page + PAGE_SIZE,
++ "accel-msg-page", &vnic->msg_page_gnt);
++ if (err) {
++ EPRINTK("couldn't make msg-page named grant\n");
++ goto fail_msg_page_grant;
++ }
++
++ /* Create xenbus msg event channel */
++ err = bind_listening_port_to_irqhandler
++ (dev->otherend_id, netfront_accel_msg_channel_irq_from_bend,
++ SA_SAMPLE_RANDOM, "vnicctrl", vnic);
++ if (err < 0) {
++ EPRINTK("Couldn't bind msg event channel\n");
++ goto fail_msg_irq;
++ }
++ vnic->msg_channel_irq = err;
++ vnic->msg_channel = irq_to_evtchn_port(vnic->msg_channel_irq);
++
++ /* Create xenbus net event channel */
++ err = bind_listening_port_to_irqhandler
++ (dev->otherend_id, netfront_accel_net_channel_irq_from_bend,
++ SA_SAMPLE_RANDOM, "vnicfront", vnic);
++ if (err < 0) {
++ EPRINTK("Couldn't bind net event channel\n");
++ goto fail_net_irq;
++ }
++ vnic->net_channel_irq = err;
++ vnic->net_channel = irq_to_evtchn_port(vnic->net_channel_irq);
++ /* Want to ensure we don't get interrupts before we're ready */
++ netfront_accel_disable_net_interrupts(vnic);
++
++ DPRINTK("otherend %d has msg ch %u (%u) and net ch %u (%u)\n",
++ dev->otherend_id, vnic->msg_channel, vnic->msg_channel_irq,
++ vnic->net_channel, vnic->net_channel_irq);
++
++ do {
++ err = xenbus_transaction_start(&tr);
++ if (err != 0) {
++ EPRINTK("%s: Transaction start failed %d\n",
++ __FUNCTION__, err);
++ goto fail_transaction;
++ }
++
++ err = xenbus_printf(tr, dev->nodename, "accel-msg-channel",
++ "%u", vnic->msg_channel);
++ if (err != 0) {
++ EPRINTK("%s: event channel xenbus write failed %d\n",
++ __FUNCTION__, err);
++ xenbus_transaction_end(tr, 1);
++ goto fail_transaction;
++ }
++
++ err = xenbus_printf(tr, dev->nodename, "accel-net-channel",
++ "%u", vnic->net_channel);
++ if (err != 0) {
++ EPRINTK("%s: net channel xenbus write failed %d\n",
++ __FUNCTION__, err);
++ xenbus_transaction_end(tr, 1);
++ goto fail_transaction;
++ }
++
++ err = xenbus_transaction_end(tr, 0);
++ } while (err == -EAGAIN);
++
++ if (err != 0) {
++ EPRINTK("%s: Transaction end failed %d\n", __FUNCTION__, err);
++ goto fail_transaction;
++ }
++
++ DPRINTK("Completed setting up domU shared state\n");
++
++ return 0;
++
++fail_transaction:
++
++ unbind_from_irqhandler(vnic->net_channel_irq, vnic);
++fail_net_irq:
++
++ unbind_from_irqhandler(vnic->msg_channel_irq, vnic);
++fail_msg_irq:
++
++ remove_named_grant(dev, "accel-ctrl-page", vnic->ctrl_page_gnt);
++fail_msg_page_grant:
++
++ remove_named_grant(dev, "accel-msg-page", vnic->msg_page_gnt);
++fail_ctrl_page_grant:
++
++ free_pages((unsigned long)vnic->shared_page, 1);
++ vnic->shared_page = NULL;
++fail_shared_page:
++
++ netfront_accel_fini_bufs(vnic->rx_bufs);
++fail_rx_bufs:
++
++ netfront_accel_fini_bufs(vnic->tx_bufs);
++fail_tx_bufs:
++
++ /* Undo the memory allocation created when we got the HELLO */
++ netfront_accel_free_buffer_mem(&vnic->bufpages,
++ vnic->rx_bufs,
++ vnic->tx_bufs);
++
++ DPRINTK("Failed to setup domU shared state with code %d\n", err);
++
++ return err;
++}
++
++
++static void vnic_remove_domU_shared_state(struct xenbus_device *dev,
++ netfront_accel_vnic *vnic)
++{
++ struct xenbus_transaction tr;
++
++ /*
++ * Don't remove any watches because we currently hold the
++ * mutex and the watches take the mutex.
++ */
++
++ DPRINTK("%s: removing event channel irq handlers %d %d\n",
++ __FUNCTION__, vnic->net_channel_irq, vnic->msg_channel_irq);
++ do {
++ if (xenbus_transaction_start(&tr) != 0)
++ break;
++ xenbus_rm(tr, dev->nodename, "accel-msg-channel");
++ xenbus_rm(tr, dev->nodename, "accel-net-channel");
++ } while (xenbus_transaction_end(tr, 0) == -EAGAIN);
++
++ unbind_from_irqhandler(vnic->net_channel_irq, vnic);
++ unbind_from_irqhandler(vnic->msg_channel_irq, vnic);
++
++ /* ungrant pages for msg channel */
++ remove_named_grant(dev, "accel-ctrl-page", vnic->ctrl_page_gnt);
++ remove_named_grant(dev, "accel-msg-page", vnic->msg_page_gnt);
++ free_pages((unsigned long)vnic->shared_page, 1);
++ vnic->shared_page = NULL;
++
++ /* ungrant pages for buffers, and free buffer memory */
++ netfront_accel_free_buffer_mem(&vnic->bufpages,
++ vnic->rx_bufs,
++ vnic->tx_bufs);
++ netfront_accel_fini_bufs(vnic->rx_bufs);
++ netfront_accel_fini_bufs(vnic->tx_bufs);
++}
++
++
++static void vnic_setup_dom0_shared_state(struct xenbus_device *dev,
++ netfront_accel_vnic *vnic)
++{
++ DPRINTK("Setting up dom0 shared state\n");
++
++ netfront_accel_vi_ctor(vnic);
++
++ /*
++ * Message processing will be enabled when this function
++ * returns, but we might have missed an interrupt. Schedule a
++ * check just in case.
++ */
++ queue_work(netfront_accel_workqueue, &vnic->msg_from_bend);
++}
++
++
++static void vnic_remove_dom0_shared_state(struct xenbus_device *dev,
++ netfront_accel_vnic *vnic)
++{
++ DPRINTK("Removing dom0 shared state\n");
++
++ vnic_stop_fastpath(vnic);
++
++ netfront_accel_vi_dtor(vnic);
++}
++
++
++/*************************************************************************/
++
++/*
++ * The following code handles accelstate changes between the frontend
++ * and the backend. In response to transitions, calls the following
++ * functions in matching pairs:
++ *
++ * vnic_setup_domU_shared_state
++ * vnic_remove_domU_shared_state
++ *
++ * vnic_setup_dom0_shared_state
++ * vnic_remove_dom0_shared_state
++ *
++ * Valid state transitions for DomU are as follows:
++ *
++ * Closed->Init on probe or in response to Init from dom0
++ *
++ * Init->Connected in response to Init from dom0
++ * Init->Closing on error providing dom0 is in Init
++ * Init->Closed on remove or in response to Closing from dom0
++ *
++ * Connected->Closing on error/remove
++ * Connected->Closed in response to Closing from dom0
++ *
++ * Closing->Closed in response to Closing from dom0
++ *
++ */
++
++
++/* Function to deal with Xenbus accel state change in backend */
++static void netfront_accel_backend_accel_changed(netfront_accel_vnic *vnic,
++ XenbusState backend_state)
++{
++ struct xenbus_device *dev = vnic->dev;
++ XenbusState frontend_state;
++ int state;
++
++ DPRINTK("%s: changing from %s to %s. nodename %s, otherend %s\n",
++ __FUNCTION__, xenbus_strstate(vnic->backend_state),
++ xenbus_strstate(backend_state), dev->nodename, dev->otherend);
++
++ /*
++ * Ignore duplicate state changes. This can happen if the
++ * backend changes state twice in quick succession and the
++ * first watch fires in the frontend after the second
++ * transition has completed.
++ */
++ if (vnic->backend_state == backend_state)
++ return;
++
++ vnic->backend_state = backend_state;
++ frontend_state = vnic->frontend_state;
++
++ switch (backend_state) {
++ case XenbusStateInitialising:
++ /*
++ * It's possible for us to miss the closed state from
++ * dom0, so do the work here.
++ */
++ if (vnic->domU_state_is_setup) {
++ vnic_remove_domU_shared_state(dev, vnic);
++ vnic->domU_state_is_setup = 0;
++ }
++
++ if (frontend_state != XenbusStateInitialising) {
++ /* Make sure the backend doesn't go away. */
++ frontend_state = XenbusStateInitialising;
++ net_accel_update_state(dev, frontend_state);
++ xenbus_scanf(XBT_NIL, dev->otherend, "accelstate", "%d", &state);
++ backend_state = (XenbusState)state;
++ if (backend_state != XenbusStateInitialising)
++ break;
++ }
++
++ /* Start the new connection. */
++ if (!vnic->removing) {
++ BUG_ON(vnic->domU_state_is_setup);
++ if (vnic_setup_domU_shared_state(dev, vnic) == 0) {
++ vnic->domU_state_is_setup = 1;
++ frontend_state = XenbusStateConnected;
++ } else
++ frontend_state = XenbusStateClosing;
++ }
++ break;
++ case XenbusStateConnected:
++ if (vnic->domU_state_is_setup &&
++ !vnic->dom0_state_is_setup) {
++ vnic_setup_dom0_shared_state(dev, vnic);
++ vnic->dom0_state_is_setup = 1;
++ }
++ break;
++ default:
++ case XenbusStateClosing:
++ if (vnic->dom0_state_is_setup) {
++ vnic_remove_dom0_shared_state(dev, vnic);
++ vnic->dom0_state_is_setup = 0;
++ }
++ frontend_state = XenbusStateClosed;
++ break;
++ case XenbusStateUnknown:
++ case XenbusStateClosed:
++ if (vnic->domU_state_is_setup) {
++ vnic_remove_domU_shared_state(dev, vnic);
++ vnic->domU_state_is_setup = 0;
++ }
++ break;
++ }
++
++ if (frontend_state != vnic->frontend_state) {
++ DPRINTK("Switching from state %s (%d) to %s (%d)\n",
++ xenbus_strstate(vnic->frontend_state),
++ vnic->frontend_state,
++ xenbus_strstate(frontend_state), frontend_state);
++ vnic->frontend_state = frontend_state;
++ net_accel_update_state(dev, frontend_state);
++ }
++
++ wake_up(&vnic->state_wait_queue);
++}
++
++
++static void backend_accel_state_change(struct xenbus_watch *watch,
++ const char **vec, unsigned int len)
++{
++ int state;
++ netfront_accel_vnic *vnic;
++ struct xenbus_device *dev;
++
++ DPRINTK("%s\n", __FUNCTION__);
++
++ vnic = container_of(watch, struct netfront_accel_vnic,
++ backend_accel_watch);
++
++ mutex_lock(&vnic->vnic_mutex);
++
++ dev = vnic->dev;
++
++ state = (int)XenbusStateUnknown;
++ xenbus_scanf(XBT_NIL, dev->otherend, "accelstate", "%d", &state);
++ netfront_accel_backend_accel_changed(vnic, state);
++
++ mutex_unlock(&vnic->vnic_mutex);
++}
++
++
++static int setup_dom0_accel_watch(struct xenbus_device *dev,
++ netfront_accel_vnic *vnic)
++{
++ int err;
++
++ DPRINTK("Setting watch on %s/%s\n", dev->otherend, "accelstate");
++
++ err = xenbus_watch_path2(dev, dev->otherend, "accelstate",
++ &vnic->backend_accel_watch,
++ backend_accel_state_change);
++ if (err) {
++ EPRINTK("%s: Failed to register xenbus watch: %d\n",
++ __FUNCTION__, err);
++ goto fail;
++ }
++ return 0;
++ fail:
++ vnic->backend_accel_watch.node = NULL;
++ return err;
++}
++
++
++int netfront_accel_probe(struct net_device *net_dev, struct xenbus_device *dev)
++{
++ netfront_accel_vnic *vnic;
++ int err;
++
++ DPRINTK("Probe passed device %s\n", dev->nodename);
++
++ vnic = netfront_accel_vnic_ctor(net_dev, dev);
++ if (IS_ERR(vnic))
++ return PTR_ERR(vnic);
++
++ /*
++ * Setup a watch on the backend accel state. This sets things
++ * going.
++ */
++ err = setup_dom0_accel_watch(dev, vnic);
++ if (err) {
++ netfront_accel_vnic_dtor(vnic);
++ EPRINTK("%s: probe failed with code %d\n", __FUNCTION__, err);
++ return err;
++ }
++
++ /*
++ * Indicate to the other end that we're ready to start unless
++ * the watch has already fired.
++ */
++ mutex_lock(&vnic->vnic_mutex);
++ VPRINTK("setup success, updating accelstate\n");
++ if (vnic->frontend_state == XenbusStateClosed) {
++ vnic->frontend_state = XenbusStateInitialising;
++ net_accel_update_state(dev, XenbusStateInitialising);
++ }
++ mutex_unlock(&vnic->vnic_mutex);
++
++ DPRINTK("Probe done device %s\n", dev->nodename);
++
++ return 0;
++}
++
++
++int netfront_accel_remove(struct xenbus_device *dev)
++{
++ struct netfront_info *np =
++ (struct netfront_info *)dev->dev.driver_data;
++ netfront_accel_vnic *vnic = (netfront_accel_vnic *)np->accel_priv;
++
++ DPRINTK("%s %s\n", __FUNCTION__, dev->nodename);
++
++ BUG_ON(vnic == NULL);
++
++ mutex_lock(&vnic->vnic_mutex);
++
++ /* Reject any attempts to connect. */
++ vnic->removing = 1;
++
++ /* Close any existing connection. */
++ if (vnic->frontend_state == XenbusStateConnected) {
++ vnic->frontend_state = XenbusStateClosing;
++ net_accel_update_state(dev, XenbusStateClosing);
++ }
++
++ mutex_unlock(&vnic->vnic_mutex);
++
++ DPRINTK("%s waiting for release of %s\n", __FUNCTION__, dev->nodename);
++
++ /*
++ * Wait for the xenbus watch to release the shared resources.
++ * This indicates that dom0 has made the transition
++ * Closing->Closed or that dom0 was in Closed or Init and no
++ * resources were mapped.
++ */
++ wait_event(vnic->state_wait_queue,
++ !vnic->domU_state_is_setup);
++
++ /*
++ * Now we don't need this watch anymore it is safe to remove
++ * it (and so synchronise with it completing if outstanding)
++ */
++ DPRINTK("%s: unregistering xenbus accel watch\n",
++ __FUNCTION__);
++ unregister_xenbus_watch(&vnic->backend_accel_watch);
++ kfree(vnic->backend_accel_watch.node);
++
++ netfront_accel_vnic_dtor(vnic);
++
++ DPRINTK("%s done %s\n", __FUNCTION__, dev->nodename);
++
++ return 0;
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_falcon_core.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_falcon_core.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_falcon_core.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_falcon_core.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1075 @@
++
++#define EFVI_FALCON_EXTENDED_P_BAR 1
++
++//////////////---- Bus Interface Unit Registers C Header ----//////////////
++#define IOM_IND_ADR_REG_OFST 0x0 // IO-mapped indirect access address register
++ #define IOM_AUTO_ADR_INC_EN_LBN 16
++ #define IOM_AUTO_ADR_INC_EN_WIDTH 1
++ #define IOM_IND_ADR_LBN 0
++ #define IOM_IND_ADR_WIDTH 16
++#define IOM_IND_DAT_REG_OFST 0x4 // IO-mapped indirect access data register
++ #define IOM_IND_DAT_LBN 0
++ #define IOM_IND_DAT_WIDTH 32
++#define ADR_REGION_REG_KER_OFST 0x0 // Address region register
++#define ADR_REGION_REG_OFST 0x0 // Address region register
++ #define ADR_REGION3_LBN 96
++ #define ADR_REGION3_WIDTH 18
++ #define ADR_REGION2_LBN 64
++ #define ADR_REGION2_WIDTH 18
++ #define ADR_REGION1_LBN 32
++ #define ADR_REGION1_WIDTH 18
++ #define ADR_REGION0_LBN 0
++ #define ADR_REGION0_WIDTH 18
++#define INT_EN_REG_KER_OFST 0x10 // Kernel driver Interrupt enable register
++ #define KER_INT_CHAR_LBN 4
++ #define KER_INT_CHAR_WIDTH 1
++ #define KER_INT_KER_LBN 3
++ #define KER_INT_KER_WIDTH 1
++ #define ILL_ADR_ERR_INT_EN_KER_LBN 2
++ #define ILL_ADR_ERR_INT_EN_KER_WIDTH 1
++ #define SRM_PERR_INT_EN_KER_LBN 1
++ #define SRM_PERR_INT_EN_KER_WIDTH 1
++ #define DRV_INT_EN_KER_LBN 0
++ #define DRV_INT_EN_KER_WIDTH 1
++#define INT_EN_REG_CHAR_OFST 0x20 // Char Driver interrupt enable register
++ #define CHAR_INT_CHAR_LBN 4
++ #define CHAR_INT_CHAR_WIDTH 1
++ #define CHAR_INT_KER_LBN 3
++ #define CHAR_INT_KER_WIDTH 1
++ #define ILL_ADR_ERR_INT_EN_CHAR_LBN 2
++ #define ILL_ADR_ERR_INT_EN_CHAR_WIDTH 1
++ #define SRM_PERR_INT_EN_CHAR_LBN 1
++ #define SRM_PERR_INT_EN_CHAR_WIDTH 1
++ #define DRV_INT_EN_CHAR_LBN 0
++ #define DRV_INT_EN_CHAR_WIDTH 1
++#define INT_ADR_REG_KER_OFST 0x30 // Interrupt host address for Kernel driver
++ #define INT_ADR_KER_LBN 0
++ #define INT_ADR_KER_WIDTH 64
++ #define DRV_INT_KER_LBN 32
++ #define DRV_INT_KER_WIDTH 1
++ #define EV_FF_HALF_INT_KER_LBN 3
++ #define EV_FF_HALF_INT_KER_WIDTH 1
++ #define EV_FF_FULL_INT_KER_LBN 2
++ #define EV_FF_FULL_INT_KER_WIDTH 1
++ #define ILL_ADR_ERR_INT_KER_LBN 1
++ #define ILL_ADR_ERR_INT_KER_WIDTH 1
++ #define SRAM_PERR_INT_KER_LBN 0
++ #define SRAM_PERR_INT_KER_WIDTH 1
++#define INT_ADR_REG_CHAR_OFST 0x40 // Interrupt host address for Char driver
++ #define INT_ADR_CHAR_LBN 0
++ #define INT_ADR_CHAR_WIDTH 64
++ #define DRV_INT_CHAR_LBN 32
++ #define DRV_INT_CHAR_WIDTH 1
++ #define EV_FF_HALF_INT_CHAR_LBN 3
++ #define EV_FF_HALF_INT_CHAR_WIDTH 1
++ #define EV_FF_FULL_INT_CHAR_LBN 2
++ #define EV_FF_FULL_INT_CHAR_WIDTH 1
++ #define ILL_ADR_ERR_INT_CHAR_LBN 1
++ #define ILL_ADR_ERR_INT_CHAR_WIDTH 1
++ #define SRAM_PERR_INT_CHAR_LBN 0
++ #define SRAM_PERR_INT_CHAR_WIDTH 1
++#define INT_ISR0_B0_OFST 0x90 // B0 only
++#define INT_ISR1_B0_OFST 0xA0
++#define INT_ACK_REG_KER_A1_OFST 0x50 // Kernel interrupt acknowledge register
++ #define RESERVED_LBN 0
++ #define RESERVED_WIDTH 32
++#define INT_ACK_REG_CHAR_A1_OFST 0x60 // CHAR interrupt acknowledge register
++ #define RESERVED_LBN 0
++ #define RESERVED_WIDTH 32
++//////////////---- Global CSR Registers C Header ----//////////////
++#define STRAP_REG_KER_OFST 0x200 // ASIC strap status register
++#define STRAP_REG_OFST 0x200 // ASIC strap status register
++ #define ONCHIP_SRAM_LBN 16
++ #define ONCHIP_SRAM_WIDTH 0
++ #define STRAP_ISCSI_EN_LBN 3
++ #define STRAP_ISCSI_EN_WIDTH 1
++ #define STRAP_PINS_LBN 0
++ #define STRAP_PINS_WIDTH 3
++#define GPIO_CTL_REG_KER_OFST 0x210 // GPIO control register
++#define GPIO_CTL_REG_OFST 0x210 // GPIO control register
++ #define GPIO_OEN_LBN 24
++ #define GPIO_OEN_WIDTH 4
++ #define GPIO_OUT_LBN 16
++ #define GPIO_OUT_WIDTH 4
++ #define GPIO_IN_LBN 8
++ #define GPIO_IN_WIDTH 4
++ #define GPIO_PWRUP_VALUE_LBN 0
++ #define GPIO_PWRUP_VALUE_WIDTH 4
++#define GLB_CTL_REG_KER_OFST 0x220 // Global control register
++#define GLB_CTL_REG_OFST 0x220 // Global control register
++ #define SWRST_LBN 0
++ #define SWRST_WIDTH 1
++#define FATAL_INTR_REG_KER_OFST 0x230 // Fatal interrupt register for Kernel
++ #define PCI_BUSERR_INT_KER_EN_LBN 43
++ #define PCI_BUSERR_INT_KER_EN_WIDTH 1
++ #define SRAM_OOB_INT_KER_EN_LBN 42
++ #define SRAM_OOB_INT_KER_EN_WIDTH 1
++ #define BUFID_OOB_INT_KER_EN_LBN 41
++ #define BUFID_OOB_INT_KER_EN_WIDTH 1
++ #define MEM_PERR_INT_KER_EN_LBN 40
++ #define MEM_PERR_INT_KER_EN_WIDTH 1
++ #define RBUF_OWN_INT_KER_EN_LBN 39
++ #define RBUF_OWN_INT_KER_EN_WIDTH 1
++ #define TBUF_OWN_INT_KER_EN_LBN 38
++ #define TBUF_OWN_INT_KER_EN_WIDTH 1
++ #define RDESCQ_OWN_INT_KER_EN_LBN 37
++ #define RDESCQ_OWN_INT_KER_EN_WIDTH 1
++ #define TDESCQ_OWN_INT_KER_EN_LBN 36
++ #define TDESCQ_OWN_INT_KER_EN_WIDTH 1
++ #define EVQ_OWN_INT_KER_EN_LBN 35
++ #define EVQ_OWN_INT_KER_EN_WIDTH 1
++ #define EVFF_OFLO_INT_KER_EN_LBN 34
++ #define EVFF_OFLO_INT_KER_EN_WIDTH 1
++ #define ILL_ADR_INT_KER_EN_LBN 33
++ #define ILL_ADR_INT_KER_EN_WIDTH 1
++ #define SRM_PERR_INT_KER_EN_LBN 32
++ #define SRM_PERR_INT_KER_EN_WIDTH 1
++ #define PCI_BUSERR_INT_KER_LBN 11
++ #define PCI_BUSERR_INT_KER_WIDTH 1
++ #define SRAM_OOB_INT_KER_LBN 10
++ #define SRAM_OOB_INT_KER_WIDTH 1
++ #define BUFID_OOB_INT_KER_LBN 9
++ #define BUFID_OOB_INT_KER_WIDTH 1
++ #define MEM_PERR_INT_KER_LBN 8
++ #define MEM_PERR_INT_KER_WIDTH 1
++ #define RBUF_OWN_INT_KER_LBN 7
++ #define RBUF_OWN_INT_KER_WIDTH 1
++ #define TBUF_OWN_INT_KER_LBN 6
++ #define TBUF_OWN_INT_KER_WIDTH 1
++ #define RDESCQ_OWN_INT_KER_LBN 5
++ #define RDESCQ_OWN_INT_KER_WIDTH 1
++ #define TDESCQ_OWN_INT_KER_LBN 4
++ #define TDESCQ_OWN_INT_KER_WIDTH 1
++ #define EVQ_OWN_INT_KER_LBN 3
++ #define EVQ_OWN_INT_KER_WIDTH 1
++ #define EVFF_OFLO_INT_KER_LBN 2
++ #define EVFF_OFLO_INT_KER_WIDTH 1
++ #define ILL_ADR_INT_KER_LBN 1
++ #define ILL_ADR_INT_KER_WIDTH 1
++ #define SRM_PERR_INT_KER_LBN 0
++ #define SRM_PERR_INT_KER_WIDTH 1
++#define FATAL_INTR_REG_OFST 0x240 // Fatal interrupt register for Char
++ #define PCI_BUSERR_INT_CHAR_EN_LBN 43
++ #define PCI_BUSERR_INT_CHAR_EN_WIDTH 1
++ #define SRAM_OOB_INT_CHAR_EN_LBN 42
++ #define SRAM_OOB_INT_CHAR_EN_WIDTH 1
++ #define BUFID_OOB_INT_CHAR_EN_LBN 41
++ #define BUFID_OOB_INT_CHAR_EN_WIDTH 1
++ #define MEM_PERR_INT_CHAR_EN_LBN 40
++ #define MEM_PERR_INT_CHAR_EN_WIDTH 1
++ #define RBUF_OWN_INT_CHAR_EN_LBN 39
++ #define RBUF_OWN_INT_CHAR_EN_WIDTH 1
++ #define TBUF_OWN_INT_CHAR_EN_LBN 38
++ #define TBUF_OWN_INT_CHAR_EN_WIDTH 1
++ #define RDESCQ_OWN_INT_CHAR_EN_LBN 37
++ #define RDESCQ_OWN_INT_CHAR_EN_WIDTH 1
++ #define TDESCQ_OWN_INT_CHAR_EN_LBN 36
++ #define TDESCQ_OWN_INT_CHAR_EN_WIDTH 1
++ #define EVQ_OWN_INT_CHAR_EN_LBN 35
++ #define EVQ_OWN_INT_CHAR_EN_WIDTH 1
++ #define EVFF_OFLO_INT_CHAR_EN_LBN 34
++ #define EVFF_OFLO_INT_CHAR_EN_WIDTH 1
++ #define ILL_ADR_INT_CHAR_EN_LBN 33
++ #define ILL_ADR_INT_CHAR_EN_WIDTH 1
++ #define SRM_PERR_INT_CHAR_EN_LBN 32
++ #define SRM_PERR_INT_CHAR_EN_WIDTH 1
++ #define FATAL_INTR_REG_EN_BITS 0xffffffffffffffffULL
++ #define PCI_BUSERR_INT_CHAR_LBN 11
++ #define PCI_BUSERR_INT_CHAR_WIDTH 1
++ #define SRAM_OOB_INT_CHAR_LBN 10
++ #define SRAM_OOB_INT_CHAR_WIDTH 1
++ #define BUFID_OOB_INT_CHAR_LBN 9
++ #define BUFID_OOB_INT_CHAR_WIDTH 1
++ #define MEM_PERR_INT_CHAR_LBN 8
++ #define MEM_PERR_INT_CHAR_WIDTH 1
++ #define RBUF_OWN_INT_CHAR_LBN 7
++ #define RBUF_OWN_INT_CHAR_WIDTH 1
++ #define TBUF_OWN_INT_CHAR_LBN 6
++ #define TBUF_OWN_INT_CHAR_WIDTH 1
++ #define RDESCQ_OWN_INT_CHAR_LBN 5
++ #define RDESCQ_OWN_INT_CHAR_WIDTH 1
++ #define TDESCQ_OWN_INT_CHAR_LBN 4
++ #define TDESCQ_OWN_INT_CHAR_WIDTH 1
++ #define EVQ_OWN_INT_CHAR_LBN 3
++ #define EVQ_OWN_INT_CHAR_WIDTH 1
++ #define EVFF_OFLO_INT_CHAR_LBN 2
++ #define EVFF_OFLO_INT_CHAR_WIDTH 1
++ #define ILL_ADR_INT_CHAR_LBN 1
++ #define ILL_ADR_INT_CHAR_WIDTH 1
++ #define SRM_PERR_INT_CHAR_LBN 0
++ #define SRM_PERR_INT_CHAR_WIDTH 1
++#define DP_CTRL_REG_OFST 0x250 // Datapath control register
++ #define FLS_EVQ_ID_LBN 0
++ #define FLS_EVQ_ID_WIDTH 12
++#define MEM_STAT_REG_KER_OFST 0x260 // Memory status register
++#define MEM_STAT_REG_OFST 0x260 // Memory status register
++ #define MEM_PERR_VEC_LBN 53
++ #define MEM_PERR_VEC_WIDTH 38
++ #define MBIST_CORR_LBN 38
++ #define MBIST_CORR_WIDTH 15
++ #define MBIST_ERR_LBN 0
++ #define MBIST_ERR_WIDTH 38
++#define DEBUG_REG_KER_OFST 0x270 // Debug register
++#define DEBUG_REG_OFST 0x270 // Debug register
++ #define DEBUG_BLK_SEL2_LBN 47
++ #define DEBUG_BLK_SEL2_WIDTH 3
++ #define DEBUG_BLK_SEL1_LBN 44
++ #define DEBUG_BLK_SEL1_WIDTH 3
++ #define DEBUG_BLK_SEL0_LBN 41
++ #define DEBUG_BLK_SEL0_WIDTH 3
++ #define MISC_DEBUG_ADDR_LBN 36
++ #define MISC_DEBUG_ADDR_WIDTH 5
++ #define SERDES_DEBUG_ADDR_LBN 31
++ #define SERDES_DEBUG_ADDR_WIDTH 5
++ #define EM_DEBUG_ADDR_LBN 26
++ #define EM_DEBUG_ADDR_WIDTH 5
++ #define SR_DEBUG_ADDR_LBN 21
++ #define SR_DEBUG_ADDR_WIDTH 5
++ #define EV_DEBUG_ADDR_LBN 16
++ #define EV_DEBUG_ADDR_WIDTH 5
++ #define RX_DEBUG_ADDR_LBN 11
++ #define RX_DEBUG_ADDR_WIDTH 5
++ #define TX_DEBUG_ADDR_LBN 6
++ #define TX_DEBUG_ADDR_WIDTH 5
++ #define BIU_DEBUG_ADDR_LBN 1
++ #define BIU_DEBUG_ADDR_WIDTH 5
++ #define DEBUG_EN_LBN 0
++ #define DEBUG_EN_WIDTH 1
++#define DRIVER_REG0_KER_OFST 0x280 // Driver scratch register 0
++#define DRIVER_REG0_OFST 0x280 // Driver scratch register 0
++ #define DRIVER_DW0_LBN 0
++ #define DRIVER_DW0_WIDTH 32
++#define DRIVER_REG1_KER_OFST 0x290 // Driver scratch register 1
++#define DRIVER_REG1_OFST 0x290 // Driver scratch register 1
++ #define DRIVER_DW1_LBN 0
++ #define DRIVER_DW1_WIDTH 32
++#define DRIVER_REG2_KER_OFST 0x2A0 // Driver scratch register 2
++#define DRIVER_REG2_OFST 0x2A0 // Driver scratch register 2
++ #define DRIVER_DW2_LBN 0
++ #define DRIVER_DW2_WIDTH 32
++#define DRIVER_REG3_KER_OFST 0x2B0 // Driver scratch register 3
++#define DRIVER_REG3_OFST 0x2B0 // Driver scratch register 3
++ #define DRIVER_DW3_LBN 0
++ #define DRIVER_DW3_WIDTH 32
++#define DRIVER_REG4_KER_OFST 0x2C0 // Driver scratch register 4
++#define DRIVER_REG4_OFST 0x2C0 // Driver scratch register 4
++ #define DRIVER_DW4_LBN 0
++ #define DRIVER_DW4_WIDTH 32
++#define DRIVER_REG5_KER_OFST 0x2D0 // Driver scratch register 5
++#define DRIVER_REG5_OFST 0x2D0 // Driver scratch register 5
++ #define DRIVER_DW5_LBN 0
++ #define DRIVER_DW5_WIDTH 32
++#define DRIVER_REG6_KER_OFST 0x2E0 // Driver scratch register 6
++#define DRIVER_REG6_OFST 0x2E0 // Driver scratch register 6
++ #define DRIVER_DW6_LBN 0
++ #define DRIVER_DW6_WIDTH 32
++#define DRIVER_REG7_KER_OFST 0x2F0 // Driver scratch register 7
++#define DRIVER_REG7_OFST 0x2F0 // Driver scratch register 7
++ #define DRIVER_DW7_LBN 0
++ #define DRIVER_DW7_WIDTH 32
++#define ALTERA_BUILD_REG_OFST 0x300 // Altera build register
++#define ALTERA_BUILD_REG_OFST 0x300 // Altera build register
++ #define ALTERA_BUILD_VER_LBN 0
++ #define ALTERA_BUILD_VER_WIDTH 32
++
++/* so called CSR spare register
++ - contains separate parity enable bits for the various internal memory blocks */
++#define MEM_PARITY_ERR_EN_REG_KER 0x310
++#define MEM_PARITY_ALL_BLOCKS_EN_LBN 64
++#define MEM_PARITY_ALL_BLOCKS_EN_WIDTH 38
++#define MEM_PARITY_TX_DATA_EN_LBN 72
++#define MEM_PARITY_TX_DATA_EN_WIDTH 2
++
++//////////////---- Event & Timer Module Registers C Header ----//////////////
++
++#if EFVI_FALCON_EXTENDED_P_BAR
++#define EVQ_RPTR_REG_KER_OFST 0x11B00 // Event queue read pointer register
++#else
++#define EVQ_RPTR_REG_KER_OFST 0x1B00 // Event queue read pointer register
++#endif
++
++#define EVQ_RPTR_REG_OFST 0xFA0000 // Event queue read pointer register array.
++ #define EVQ_RPTR_LBN 0
++ #define EVQ_RPTR_WIDTH 15
++
++#if EFVI_FALCON_EXTENDED_P_BAR
++#define EVQ_PTR_TBL_KER_OFST 0x11A00 // Event queue pointer table for kernel access
++#else
++#define EVQ_PTR_TBL_KER_OFST 0x1A00 // Event queue pointer table for kernel access
++#endif
++
++#define EVQ_PTR_TBL_CHAR_OFST 0xF60000 // Event queue pointer table for char direct access
++ #define EVQ_WKUP_OR_INT_EN_LBN 39
++ #define EVQ_WKUP_OR_INT_EN_WIDTH 1
++ #define EVQ_NXT_WPTR_LBN 24
++ #define EVQ_NXT_WPTR_WIDTH 15
++ #define EVQ_EN_LBN 23
++ #define EVQ_EN_WIDTH 1
++ #define EVQ_SIZE_LBN 20
++ #define EVQ_SIZE_WIDTH 3
++ #define EVQ_BUF_BASE_ID_LBN 0
++ #define EVQ_BUF_BASE_ID_WIDTH 20
++#define TIMER_CMD_REG_KER_OFST 0x420 // Timer table for kernel access. Page-mapped
++#define TIMER_CMD_REG_PAGE4_OFST 0x8420 // Timer table for user-level access. Page-mapped. For lowest 1K queues.
++#define TIMER_CMD_REG_PAGE123K_OFST 0x1000420 // Timer table for user-level access. Page-mapped. For upper 3K queues.
++#define TIMER_TBL_OFST 0xF70000 // Timer table for char driver direct access
++ #define TIMER_MODE_LBN 12
++ #define TIMER_MODE_WIDTH 2
++ #define TIMER_VAL_LBN 0
++ #define TIMER_VAL_WIDTH 12
++ #define TIMER_MODE_INT_HLDOFF 2
++ #define EVQ_BUF_SIZE_LBN 0
++ #define EVQ_BUF_SIZE_WIDTH 1
++#define DRV_EV_REG_KER_OFST 0x440 // Driver generated event register
++#define DRV_EV_REG_OFST 0x440 // Driver generated event register
++ #define DRV_EV_QID_LBN 64
++ #define DRV_EV_QID_WIDTH 12
++ #define DRV_EV_DATA_LBN 0
++ #define DRV_EV_DATA_WIDTH 64
++#define EVQ_CTL_REG_KER_OFST 0x450 // Event queue control register
++#define EVQ_CTL_REG_OFST 0x450 // Event queue control register
++ #define RX_EVQ_WAKEUP_MASK_B0_LBN 15
++ #define RX_EVQ_WAKEUP_MASK_B0_WIDTH 6
++ #define EVQ_OWNERR_CTL_LBN 14
++ #define EVQ_OWNERR_CTL_WIDTH 1
++ #define EVQ_FIFO_AF_TH_LBN 8
++ #define EVQ_FIFO_AF_TH_WIDTH 6
++ #define EVQ_FIFO_NOTAF_TH_LBN 0
++ #define EVQ_FIFO_NOTAF_TH_WIDTH 6
++//////////////---- SRAM Module Registers C Header ----//////////////
++#define BUF_TBL_CFG_REG_KER_OFST 0x600 // Buffer table configuration register
++#define BUF_TBL_CFG_REG_OFST 0x600 // Buffer table configuration register
++ #define BUF_TBL_MODE_LBN 3
++ #define BUF_TBL_MODE_WIDTH 1
++#define SRM_RX_DC_CFG_REG_KER_OFST 0x610 // SRAM receive descriptor cache configuration register
++#define SRM_RX_DC_CFG_REG_OFST 0x610 // SRAM receive descriptor cache configuration register
++ #define SRM_RX_DC_BASE_ADR_LBN 0
++ #define SRM_RX_DC_BASE_ADR_WIDTH 21
++#define SRM_TX_DC_CFG_REG_KER_OFST 0x620 // SRAM transmit descriptor cache configuration register
++#define SRM_TX_DC_CFG_REG_OFST 0x620 // SRAM transmit descriptor cache configuration register
++ #define SRM_TX_DC_BASE_ADR_LBN 0
++ #define SRM_TX_DC_BASE_ADR_WIDTH 21
++#define SRM_CFG_REG_KER_OFST 0x630 // SRAM configuration register
++#define SRM_CFG_REG_OFST 0x630 // SRAM configuration register
++ #define SRAM_OOB_ADR_INTEN_LBN 5
++ #define SRAM_OOB_ADR_INTEN_WIDTH 1
++ #define SRAM_OOB_BUF_INTEN_LBN 4
++ #define SRAM_OOB_BUF_INTEN_WIDTH 1
++ #define SRAM_BT_INIT_EN_LBN 3
++ #define SRAM_BT_INIT_EN_WIDTH 1
++ #define SRM_NUM_BANK_LBN 2
++ #define SRM_NUM_BANK_WIDTH 1
++ #define SRM_BANK_SIZE_LBN 0
++ #define SRM_BANK_SIZE_WIDTH 2
++#define BUF_TBL_UPD_REG_KER_OFST 0x650 // Buffer table update register
++#define BUF_TBL_UPD_REG_OFST 0x650 // Buffer table update register
++ #define BUF_UPD_CMD_LBN 63
++ #define BUF_UPD_CMD_WIDTH 1
++ #define BUF_CLR_CMD_LBN 62
++ #define BUF_CLR_CMD_WIDTH 1
++ #define BUF_CLR_END_ID_LBN 32
++ #define BUF_CLR_END_ID_WIDTH 20
++ #define BUF_CLR_START_ID_LBN 0
++ #define BUF_CLR_START_ID_WIDTH 20
++#define SRM_UPD_EVQ_REG_KER_OFST 0x660 // Buffer table update register
++#define SRM_UPD_EVQ_REG_OFST 0x660 // Buffer table update register
++ #define SRM_UPD_EVQ_ID_LBN 0
++ #define SRM_UPD_EVQ_ID_WIDTH 12
++#define SRAM_PARITY_REG_KER_OFST 0x670 // SRAM parity register.
++#define SRAM_PARITY_REG_OFST 0x670 // SRAM parity register.
++ #define FORCE_SRAM_PERR_LBN 0
++ #define FORCE_SRAM_PERR_WIDTH 1
++
++#if EFVI_FALCON_EXTENDED_P_BAR
++#define BUF_HALF_TBL_KER_OFST 0x18000 // Buffer table in half buffer table mode direct access by kernel driver
++#else
++#define BUF_HALF_TBL_KER_OFST 0x8000 // Buffer table in half buffer table mode direct access by kernel driver
++#endif
++
++
++#define BUF_HALF_TBL_OFST 0x800000 // Buffer table in half buffer table mode direct access by char driver
++ #define BUF_ADR_HBUF_ODD_LBN 44
++ #define BUF_ADR_HBUF_ODD_WIDTH 20
++ #define BUF_OWNER_ID_HBUF_ODD_LBN 32
++ #define BUF_OWNER_ID_HBUF_ODD_WIDTH 12
++ #define BUF_ADR_HBUF_EVEN_LBN 12
++ #define BUF_ADR_HBUF_EVEN_WIDTH 20
++ #define BUF_OWNER_ID_HBUF_EVEN_LBN 0
++ #define BUF_OWNER_ID_HBUF_EVEN_WIDTH 12
++
++
++#if EFVI_FALCON_EXTENDED_P_BAR
++#define BUF_FULL_TBL_KER_OFST 0x18000 // Buffer table in full buffer table mode direct access by kernel driver
++#else
++#define BUF_FULL_TBL_KER_OFST 0x8000 // Buffer table in full buffer table mode direct access by kernel driver
++#endif
++
++
++
++
++#define BUF_FULL_TBL_OFST 0x800000 // Buffer table in full buffer table mode direct access by char driver
++ #define IP_DAT_BUF_SIZE_LBN 50
++ #define IP_DAT_BUF_SIZE_WIDTH 1
++ #define BUF_ADR_REGION_LBN 48
++ #define BUF_ADR_REGION_WIDTH 2
++ #define BUF_ADR_FBUF_LBN 14
++ #define BUF_ADR_FBUF_WIDTH 34
++ #define BUF_OWNER_ID_FBUF_LBN 0
++ #define BUF_OWNER_ID_FBUF_WIDTH 14
++#define SRM_DBG_REG_OFST 0x3000000 // SRAM debug access
++ #define SRM_DBG_LBN 0
++ #define SRM_DBG_WIDTH 64
++//////////////---- RX Datapath Registers C Header ----//////////////
++
++#define RX_CFG_REG_KER_OFST 0x800 // Receive configuration register
++#define RX_CFG_REG_OFST 0x800 // Receive configuration register
++
++#if !defined(FALCON_64K_RXFIFO) && !defined(FALCON_PRE_02020029)
++# if !defined(FALCON_128K_RXFIFO)
++# define FALCON_128K_RXFIFO
++# endif
++#endif
++
++#if defined(FALCON_128K_RXFIFO)
++
++/* new for B0 */
++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 48
++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++ #define RX_INGR_EN_B0_LBN 47
++ #define RX_INGR_EN_B0_WIDTH 1
++ #define RX_TOEP_IPV4_B0_LBN 46
++ #define RX_TOEP_IPV4_B0_WIDTH 1
++ #define RX_HASH_ALG_B0_LBN 45
++ #define RX_HASH_ALG_B0_WIDTH 1
++ #define RX_HASH_INSERT_HDR_B0_LBN 44
++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++ #define RX_DESC_PUSH_EN_B0_LBN 43
++ #define RX_DESC_PUSH_EN_B0_WIDTH 1
++ #define RX_RDW_PATCH_EN_LBN 42 /* Non head of line blocking */
++ #define RX_RDW_PATCH_EN_WIDTH 1
++ #define RX_PCI_BURST_SIZE_B0_LBN 39
++ #define RX_PCI_BURST_SIZE_B0_WIDTH 3
++ #define RX_OWNERR_CTL_B0_LBN 38
++ #define RX_OWNERR_CTL_B0_WIDTH 1
++ #define RX_XON_TX_TH_B0_LBN 33
++ #define RX_XON_TX_TH_B0_WIDTH 5
++ #define RX_XOFF_TX_TH_B0_LBN 28
++ #define RX_XOFF_TX_TH_B0_WIDTH 5
++ #define RX_USR_BUF_SIZE_B0_LBN 19
++ #define RX_USR_BUF_SIZE_B0_WIDTH 9
++ #define RX_XON_MAC_TH_B0_LBN 10
++ #define RX_XON_MAC_TH_B0_WIDTH 9
++ #define RX_XOFF_MAC_TH_B0_LBN 1
++ #define RX_XOFF_MAC_TH_B0_WIDTH 9
++ #define RX_XOFF_MAC_EN_B0_LBN 0
++ #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#elif !defined(FALCON_PRE_02020029)
++/* new for B0 */
++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 46
++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++ #define RX_INGR_EN_B0_LBN 45
++ #define RX_INGR_EN_B0_WIDTH 1
++ #define RX_TOEP_IPV4_B0_LBN 44
++ #define RX_TOEP_IPV4_B0_WIDTH 1
++ #define RX_HASH_ALG_B0_LBN 43
++ #define RX_HASH_ALG_B0_WIDTH 41
++ #define RX_HASH_INSERT_HDR_B0_LBN 42
++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++ #define RX_DESC_PUSH_EN_B0_LBN 41
++ #define RX_DESC_PUSH_EN_B0_WIDTH 1
++ #define RX_PCI_BURST_SIZE_B0_LBN 37
++ #define RX_PCI_BURST_SIZE_B0_WIDTH 3
++ #define RX_OWNERR_CTL_B0_LBN 36
++ #define RX_OWNERR_CTL_B0_WIDTH 1
++ #define RX_XON_TX_TH_B0_LBN 31
++ #define RX_XON_TX_TH_B0_WIDTH 5
++ #define RX_XOFF_TX_TH_B0_LBN 26
++ #define RX_XOFF_TX_TH_B0_WIDTH 5
++ #define RX_USR_BUF_SIZE_B0_LBN 17
++ #define RX_USR_BUF_SIZE_B0_WIDTH 9
++ #define RX_XON_MAC_TH_B0_LBN 9
++ #define RX_XON_MAC_TH_B0_WIDTH 8
++ #define RX_XOFF_MAC_TH_B0_LBN 1
++ #define RX_XOFF_MAC_TH_B0_WIDTH 8
++ #define RX_XOFF_MAC_EN_B0_LBN 0
++ #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#else
++/* new for B0 */
++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 44
++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++ #define RX_INGR_EN_B0_LBN 43
++ #define RX_INGR_EN_B0_WIDTH 1
++ #define RX_TOEP_IPV4_B0_LBN 42
++ #define RX_TOEP_IPV4_B0_WIDTH 1
++ #define RX_HASH_ALG_B0_LBN 41
++ #define RX_HASH_ALG_B0_WIDTH 41
++ #define RX_HASH_INSERT_HDR_B0_LBN 40
++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++ #define RX_DESC_PUSH_EN_B0_LBN 35
++ #define RX_DESC_PUSH_EN_B0_WIDTH 1
++ #define RX_PCI_BURST_SIZE_B0_LBN 35
++ #define RX_PCI_BURST_SIZE_B0_WIDTH 2
++ #define RX_OWNERR_CTL_B0_LBN 34
++ #define RX_OWNERR_CTL_B0_WIDTH 1
++ #define RX_XON_TX_TH_B0_LBN 29
++ #define RX_XON_TX_TH_B0_WIDTH 5
++ #define RX_XOFF_TX_TH_B0_LBN 24
++ #define RX_XOFF_TX_TH_B0_WIDTH 5
++ #define RX_USR_BUF_SIZE_B0_LBN 15
++ #define RX_USR_BUF_SIZE_B0_WIDTH 9
++ #define RX_XON_MAC_TH_B0_LBN 8
++ #define RX_XON_MAC_TH_B0_WIDTH 7
++ #define RX_XOFF_MAC_TH_B0_LBN 1
++ #define RX_XOFF_MAC_TH_B0_WIDTH 7
++ #define RX_XOFF_MAC_EN_B0_LBN 0
++ #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#endif
++
++/* A0/A1 */
++ #define RX_PUSH_EN_A1_LBN 35
++ #define RX_PUSH_EN_A1_WIDTH 1
++ #define RX_PCI_BURST_SIZE_A1_LBN 31
++ #define RX_PCI_BURST_SIZE_A1_WIDTH 3
++ #define RX_OWNERR_CTL_A1_LBN 30
++ #define RX_OWNERR_CTL_A1_WIDTH 1
++ #define RX_XON_TX_TH_A1_LBN 25
++ #define RX_XON_TX_TH_A1_WIDTH 5
++ #define RX_XOFF_TX_TH_A1_LBN 20
++ #define RX_XOFF_TX_TH_A1_WIDTH 5
++ #define RX_USR_BUF_SIZE_A1_LBN 11
++ #define RX_USR_BUF_SIZE_A1_WIDTH 9
++ #define RX_XON_MAC_TH_A1_LBN 6
++ #define RX_XON_MAC_TH_A1_WIDTH 5
++ #define RX_XOFF_MAC_TH_A1_LBN 1
++ #define RX_XOFF_MAC_TH_A1_WIDTH 5
++ #define RX_XOFF_MAC_EN_A1_LBN 0
++ #define RX_XOFF_MAC_EN_A1_WIDTH 1
++
++#define RX_FILTER_CTL_REG_OFST 0x810 // Receive filter control registers
++ #define SCATTER_ENBL_NO_MATCH_Q_B0_LBN 40
++ #define SCATTER_ENBL_NO_MATCH_Q_B0_WIDTH 1
++ #define UDP_FULL_SRCH_LIMIT_LBN 32
++ #define UDP_FULL_SRCH_LIMIT_WIDTH 8
++ #define NUM_KER_LBN 24
++ #define NUM_KER_WIDTH 2
++ #define UDP_WILD_SRCH_LIMIT_LBN 16
++ #define UDP_WILD_SRCH_LIMIT_WIDTH 8
++ #define TCP_WILD_SRCH_LIMIT_LBN 8
++ #define TCP_WILD_SRCH_LIMIT_WIDTH 8
++ #define TCP_FULL_SRCH_LIMIT_LBN 0
++ #define TCP_FULL_SRCH_LIMIT_WIDTH 8
++#define RX_FLUSH_DESCQ_REG_KER_OFST 0x820 // Receive flush descriptor queue register
++#define RX_FLUSH_DESCQ_REG_OFST 0x820 // Receive flush descriptor queue register
++ #define RX_FLUSH_DESCQ_CMD_LBN 24
++ #define RX_FLUSH_DESCQ_CMD_WIDTH 1
++ #define RX_FLUSH_EVQ_ID_LBN 12
++ #define RX_FLUSH_EVQ_ID_WIDTH 12
++ #define RX_FLUSH_DESCQ_LBN 0
++ #define RX_FLUSH_DESCQ_WIDTH 12
++#define RX_DESC_UPD_REG_KER_OFST 0x830 // Kernel receive descriptor update register. Page-mapped
++#define RX_DESC_UPD_REG_PAGE4_OFST 0x8830 // Char & user receive descriptor update register. Page-mapped. For lowest 1K queues.
++#define RX_DESC_UPD_REG_PAGE123K_OFST 0x1000830 // Char & user receive descriptor update register. Page-mapped. For upper 3K queues.
++ #define RX_DESC_WPTR_LBN 96
++ #define RX_DESC_WPTR_WIDTH 12
++ #define RX_DESC_PUSH_CMD_LBN 95
++ #define RX_DESC_PUSH_CMD_WIDTH 1
++ #define RX_DESC_LBN 0
++ #define RX_DESC_WIDTH 64
++ #define RX_KER_DESC_LBN 0
++ #define RX_KER_DESC_WIDTH 64
++ #define RX_USR_DESC_LBN 0
++ #define RX_USR_DESC_WIDTH 32
++#define RX_DC_CFG_REG_KER_OFST 0x840 // Receive descriptor cache configuration register
++#define RX_DC_CFG_REG_OFST 0x840 // Receive descriptor cache configuration register
++ #define RX_DC_SIZE_LBN 0
++ #define RX_DC_SIZE_WIDTH 2
++#define RX_DC_PF_WM_REG_KER_OFST 0x850 // Receive descriptor cache pre-fetch watermark register
++#define RX_DC_PF_WM_REG_OFST 0x850 // Receive descriptor cache pre-fetch watermark register
++ #define RX_DC_PF_LWM_LO_LBN 0
++ #define RX_DC_PF_LWM_LO_WIDTH 6
++
++#define RX_RSS_TKEY_B0_OFST 0x860 // RSS Toeplitz hash key (B0 only)
++
++#define RX_NODESC_DROP_REG 0x880
++ #define RX_NODESC_DROP_CNT_LBN 0
++ #define RX_NODESC_DROP_CNT_WIDTH 16
++
++#define XM_TX_CFG_REG_OFST 0x1230
++ #define XM_AUTO_PAD_LBN 5
++ #define XM_AUTO_PAD_WIDTH 1
++
++#define RX_FILTER_TBL0_OFST 0xF00000 // Receive filter table - even entries
++ #define RSS_EN_0_B0_LBN 110
++ #define RSS_EN_0_B0_WIDTH 1
++ #define SCATTER_EN_0_B0_LBN 109
++ #define SCATTER_EN_0_B0_WIDTH 1
++ #define TCP_UDP_0_LBN 108
++ #define TCP_UDP_0_WIDTH 1
++ #define RXQ_ID_0_LBN 96
++ #define RXQ_ID_0_WIDTH 12
++ #define DEST_IP_0_LBN 64
++ #define DEST_IP_0_WIDTH 32
++ #define DEST_PORT_TCP_0_LBN 48
++ #define DEST_PORT_TCP_0_WIDTH 16
++ #define SRC_IP_0_LBN 16
++ #define SRC_IP_0_WIDTH 32
++ #define SRC_TCP_DEST_UDP_0_LBN 0
++ #define SRC_TCP_DEST_UDP_0_WIDTH 16
++#define RX_FILTER_TBL1_OFST 0xF00010 // Receive filter table - odd entries
++ #define RSS_EN_1_B0_LBN 110
++ #define RSS_EN_1_B0_WIDTH 1
++ #define SCATTER_EN_1_B0_LBN 109
++ #define SCATTER_EN_1_B0_WIDTH 1
++ #define TCP_UDP_1_LBN 108
++ #define TCP_UDP_1_WIDTH 1
++ #define RXQ_ID_1_LBN 96
++ #define RXQ_ID_1_WIDTH 12
++ #define DEST_IP_1_LBN 64
++ #define DEST_IP_1_WIDTH 32
++ #define DEST_PORT_TCP_1_LBN 48
++ #define DEST_PORT_TCP_1_WIDTH 16
++ #define SRC_IP_1_LBN 16
++ #define SRC_IP_1_WIDTH 32
++ #define SRC_TCP_DEST_UDP_1_LBN 0
++ #define SRC_TCP_DEST_UDP_1_WIDTH 16
++
++#if EFVI_FALCON_EXTENDED_P_BAR
++#define RX_DESC_PTR_TBL_KER_OFST 0x11800 // Receive descriptor pointer kernel access
++#else
++#define RX_DESC_PTR_TBL_KER_OFST 0x1800 // Receive descriptor pointer kernel access
++#endif
++
++
++#define RX_DESC_PTR_TBL_OFST 0xF40000 // Receive descriptor pointer table
++ #define RX_ISCSI_DDIG_EN_LBN 88
++ #define RX_ISCSI_DDIG_EN_WIDTH 1
++ #define RX_ISCSI_HDIG_EN_LBN 87
++ #define RX_ISCSI_HDIG_EN_WIDTH 1
++ #define RX_DESC_PREF_ACT_LBN 86
++ #define RX_DESC_PREF_ACT_WIDTH 1
++ #define RX_DC_HW_RPTR_LBN 80
++ #define RX_DC_HW_RPTR_WIDTH 6
++ #define RX_DESCQ_HW_RPTR_LBN 68
++ #define RX_DESCQ_HW_RPTR_WIDTH 12
++ #define RX_DESCQ_SW_WPTR_LBN 56
++ #define RX_DESCQ_SW_WPTR_WIDTH 12
++ #define RX_DESCQ_BUF_BASE_ID_LBN 36
++ #define RX_DESCQ_BUF_BASE_ID_WIDTH 20
++ #define RX_DESCQ_EVQ_ID_LBN 24
++ #define RX_DESCQ_EVQ_ID_WIDTH 12
++ #define RX_DESCQ_OWNER_ID_LBN 10
++ #define RX_DESCQ_OWNER_ID_WIDTH 14
++ #define RX_DESCQ_LABEL_LBN 5
++ #define RX_DESCQ_LABEL_WIDTH 5
++ #define RX_DESCQ_SIZE_LBN 3
++ #define RX_DESCQ_SIZE_WIDTH 2
++ #define RX_DESCQ_TYPE_LBN 2
++ #define RX_DESCQ_TYPE_WIDTH 1
++ #define RX_DESCQ_JUMBO_LBN 1
++ #define RX_DESCQ_JUMBO_WIDTH 1
++ #define RX_DESCQ_EN_LBN 0
++ #define RX_DESCQ_EN_WIDTH 1
++
++
++#define RX_RSS_INDIR_TBL_B0_OFST 0xFB0000 // RSS indirection table (B0 only)
++ #define RX_RSS_INDIR_ENT_B0_LBN 0
++ #define RX_RSS_INDIR_ENT_B0_WIDTH 6
++
++//////////////---- TX Datapath Registers C Header ----//////////////
++#define TX_FLUSH_DESCQ_REG_KER_OFST 0xA00 // Transmit flush descriptor queue register
++#define TX_FLUSH_DESCQ_REG_OFST 0xA00 // Transmit flush descriptor queue register
++ #define TX_FLUSH_DESCQ_CMD_LBN 12
++ #define TX_FLUSH_DESCQ_CMD_WIDTH 1
++ #define TX_FLUSH_DESCQ_LBN 0
++ #define TX_FLUSH_DESCQ_WIDTH 12
++#define TX_DESC_UPD_REG_KER_OFST 0xA10 // Kernel transmit descriptor update register. Page-mapped
++#define TX_DESC_UPD_REG_PAGE4_OFST 0x8A10 // Char & user transmit descriptor update register. Page-mapped
++#define TX_DESC_UPD_REG_PAGE123K_OFST 0x1000A10 // Char & user transmit descriptor update register. Page-mapped
++ #define TX_DESC_WPTR_LBN 96
++ #define TX_DESC_WPTR_WIDTH 12
++ #define TX_DESC_PUSH_CMD_LBN 95
++ #define TX_DESC_PUSH_CMD_WIDTH 1
++ #define TX_DESC_LBN 0
++ #define TX_DESC_WIDTH 95
++ #define TX_KER_DESC_LBN 0
++ #define TX_KER_DESC_WIDTH 64
++ #define TX_USR_DESC_LBN 0
++ #define TX_USR_DESC_WIDTH 64
++#define TX_DC_CFG_REG_KER_OFST 0xA20 // Transmit descriptor cache configuration register
++#define TX_DC_CFG_REG_OFST 0xA20 // Transmit descriptor cache configuration register
++ #define TX_DC_SIZE_LBN 0
++ #define TX_DC_SIZE_WIDTH 2
++
++#if EFVI_FALCON_EXTENDED_P_BAR
++#define TX_DESC_PTR_TBL_KER_OFST 0x11900 // Transmit descriptor pointer.
++#else
++#define TX_DESC_PTR_TBL_KER_OFST 0x1900 // Transmit descriptor pointer.
++#endif
++
++
++#define TX_DESC_PTR_TBL_OFST 0xF50000 // Transmit descriptor pointer
++ #define TX_NON_IP_DROP_DIS_B0_LBN 91
++ #define TX_NON_IP_DROP_DIS_B0_WIDTH 1
++ #define TX_IP_CHKSM_DIS_B0_LBN 90
++ #define TX_IP_CHKSM_DIS_B0_WIDTH 1
++ #define TX_TCP_CHKSM_DIS_B0_LBN 89
++ #define TX_TCP_CHKSM_DIS_B0_WIDTH 1
++ #define TX_DESCQ_EN_LBN 88
++ #define TX_DESCQ_EN_WIDTH 1
++ #define TX_ISCSI_DDIG_EN_LBN 87
++ #define TX_ISCSI_DDIG_EN_WIDTH 1
++ #define TX_ISCSI_HDIG_EN_LBN 86
++ #define TX_ISCSI_HDIG_EN_WIDTH 1
++ #define TX_DC_HW_RPTR_LBN 80
++ #define TX_DC_HW_RPTR_WIDTH 6
++ #define TX_DESCQ_HW_RPTR_LBN 68
++ #define TX_DESCQ_HW_RPTR_WIDTH 12
++ #define TX_DESCQ_SW_WPTR_LBN 56
++ #define TX_DESCQ_SW_WPTR_WIDTH 12
++ #define TX_DESCQ_BUF_BASE_ID_LBN 36
++ #define TX_DESCQ_BUF_BASE_ID_WIDTH 20
++ #define TX_DESCQ_EVQ_ID_LBN 24
++ #define TX_DESCQ_EVQ_ID_WIDTH 12
++ #define TX_DESCQ_OWNER_ID_LBN 10
++ #define TX_DESCQ_OWNER_ID_WIDTH 14
++ #define TX_DESCQ_LABEL_LBN 5
++ #define TX_DESCQ_LABEL_WIDTH 5
++ #define TX_DESCQ_SIZE_LBN 3
++ #define TX_DESCQ_SIZE_WIDTH 2
++ #define TX_DESCQ_TYPE_LBN 1
++ #define TX_DESCQ_TYPE_WIDTH 2
++ #define TX_DESCQ_FLUSH_LBN 0
++ #define TX_DESCQ_FLUSH_WIDTH 1
++#define TX_CFG_REG_KER_OFST 0xA50 // Transmit configuration register
++#define TX_CFG_REG_OFST 0xA50 // Transmit configuration register
++ #define TX_IP_ID_P1_OFS_LBN 32
++ #define TX_IP_ID_P1_OFS_WIDTH 15
++ #define TX_IP_ID_P0_OFS_LBN 16
++ #define TX_IP_ID_P0_OFS_WIDTH 15
++ #define TX_TURBO_EN_LBN 3
++ #define TX_TURBO_EN_WIDTH 1
++ #define TX_OWNERR_CTL_LBN 2
++ #define TX_OWNERR_CTL_WIDTH 2
++ #define TX_NON_IP_DROP_DIS_LBN 1
++ #define TX_NON_IP_DROP_DIS_WIDTH 1
++ #define TX_IP_ID_REP_EN_LBN 0
++ #define TX_IP_ID_REP_EN_WIDTH 1
++#define TX_RESERVED_REG_KER_OFST 0xA80 // Transmit configuration register
++#define TX_RESERVED_REG_OFST 0xA80 // Transmit configuration register
++ #define TX_CSR_PUSH_EN_LBN 89
++ #define TX_CSR_PUSH_EN_WIDTH 1
++ #define TX_RX_SPACER_LBN 64
++ #define TX_RX_SPACER_WIDTH 8
++ #define TX_SW_EV_EN_LBN 59
++ #define TX_SW_EV_EN_WIDTH 1
++ #define TX_RX_SPACER_EN_LBN 57
++ #define TX_RX_SPACER_EN_WIDTH 1
++ #define TX_CSR_PREF_WD_TMR_LBN 24
++ #define TX_CSR_PREF_WD_TMR_WIDTH 16
++ #define TX_CSR_ONLY1TAG_LBN 21
++ #define TX_CSR_ONLY1TAG_WIDTH 1
++ #define TX_PREF_THRESHOLD_LBN 19
++ #define TX_PREF_THRESHOLD_WIDTH 2
++ #define TX_ONE_PKT_PER_Q_LBN 18
++ #define TX_ONE_PKT_PER_Q_WIDTH 1
++ #define TX_DIS_NON_IP_EV_LBN 17
++ #define TX_DIS_NON_IP_EV_WIDTH 1
++ #define TX_DMA_SPACER_LBN 8
++ #define TX_DMA_SPACER_WIDTH 8
++ #define TX_FLUSH_MIN_LEN_EN_B0_LBN 7
++ #define TX_FLUSH_MIN_LEN_EN_B0_WIDTH 1
++ #define TX_TCP_DIS_A1_LBN 7
++ #define TX_TCP_DIS_A1_WIDTH 1
++ #define TX_IP_DIS_A1_LBN 6
++ #define TX_IP_DIS_A1_WIDTH 1
++ #define TX_MAX_CPL_LBN 2
++ #define TX_MAX_CPL_WIDTH 2
++ #define TX_MAX_PREF_LBN 0
++ #define TX_MAX_PREF_WIDTH 2
++#define TX_VLAN_REG_OFST 0xAE0 // Transmit VLAN tag register
++ #define TX_VLAN_EN_LBN 127
++ #define TX_VLAN_EN_WIDTH 1
++ #define TX_VLAN7_PORT1_EN_LBN 125
++ #define TX_VLAN7_PORT1_EN_WIDTH 1
++ #define TX_VLAN7_PORT0_EN_LBN 124
++ #define TX_VLAN7_PORT0_EN_WIDTH 1
++ #define TX_VLAN7_LBN 112
++ #define TX_VLAN7_WIDTH 12
++ #define TX_VLAN6_PORT1_EN_LBN 109
++ #define TX_VLAN6_PORT1_EN_WIDTH 1
++ #define TX_VLAN6_PORT0_EN_LBN 108
++ #define TX_VLAN6_PORT0_EN_WIDTH 1
++ #define TX_VLAN6_LBN 96
++ #define TX_VLAN6_WIDTH 12
++ #define TX_VLAN5_PORT1_EN_LBN 93
++ #define TX_VLAN5_PORT1_EN_WIDTH 1
++ #define TX_VLAN5_PORT0_EN_LBN 92
++ #define TX_VLAN5_PORT0_EN_WIDTH 1
++ #define TX_VLAN5_LBN 80
++ #define TX_VLAN5_WIDTH 12
++ #define TX_VLAN4_PORT1_EN_LBN 77
++ #define TX_VLAN4_PORT1_EN_WIDTH 1
++ #define TX_VLAN4_PORT0_EN_LBN 76
++ #define TX_VLAN4_PORT0_EN_WIDTH 1
++ #define TX_VLAN4_LBN 64
++ #define TX_VLAN4_WIDTH 12
++ #define TX_VLAN3_PORT1_EN_LBN 61
++ #define TX_VLAN3_PORT1_EN_WIDTH 1
++ #define TX_VLAN3_PORT0_EN_LBN 60
++ #define TX_VLAN3_PORT0_EN_WIDTH 1
++ #define TX_VLAN3_LBN 48
++ #define TX_VLAN3_WIDTH 12
++ #define TX_VLAN2_PORT1_EN_LBN 45
++ #define TX_VLAN2_PORT1_EN_WIDTH 1
++ #define TX_VLAN2_PORT0_EN_LBN 44
++ #define TX_VLAN2_PORT0_EN_WIDTH 1
++ #define TX_VLAN2_LBN 32
++ #define TX_VLAN2_WIDTH 12
++ #define TX_VLAN1_PORT1_EN_LBN 29
++ #define TX_VLAN1_PORT1_EN_WIDTH 1
++ #define TX_VLAN1_PORT0_EN_LBN 28
++ #define TX_VLAN1_PORT0_EN_WIDTH 1
++ #define TX_VLAN1_LBN 16
++ #define TX_VLAN1_WIDTH 12
++ #define TX_VLAN0_PORT1_EN_LBN 13
++ #define TX_VLAN0_PORT1_EN_WIDTH 1
++ #define TX_VLAN0_PORT0_EN_LBN 12
++ #define TX_VLAN0_PORT0_EN_WIDTH 1
++ #define TX_VLAN0_LBN 0
++ #define TX_VLAN0_WIDTH 12
++#define TX_FIL_CTL_REG_OFST 0xAF0 // Transmit filter control register
++ #define TX_MADR1_FIL_EN_LBN 65
++ #define TX_MADR1_FIL_EN_WIDTH 1
++ #define TX_MADR0_FIL_EN_LBN 64
++ #define TX_MADR0_FIL_EN_WIDTH 1
++ #define TX_IPFIL31_PORT1_EN_LBN 63
++ #define TX_IPFIL31_PORT1_EN_WIDTH 1
++ #define TX_IPFIL31_PORT0_EN_LBN 62
++ #define TX_IPFIL31_PORT0_EN_WIDTH 1
++ #define TX_IPFIL30_PORT1_EN_LBN 61
++ #define TX_IPFIL30_PORT1_EN_WIDTH 1
++ #define TX_IPFIL30_PORT0_EN_LBN 60
++ #define TX_IPFIL30_PORT0_EN_WIDTH 1
++ #define TX_IPFIL29_PORT1_EN_LBN 59
++ #define TX_IPFIL29_PORT1_EN_WIDTH 1
++ #define TX_IPFIL29_PORT0_EN_LBN 58
++ #define TX_IPFIL29_PORT0_EN_WIDTH 1
++ #define TX_IPFIL28_PORT1_EN_LBN 57
++ #define TX_IPFIL28_PORT1_EN_WIDTH 1
++ #define TX_IPFIL28_PORT0_EN_LBN 56
++ #define TX_IPFIL28_PORT0_EN_WIDTH 1
++ #define TX_IPFIL27_PORT1_EN_LBN 55
++ #define TX_IPFIL27_PORT1_EN_WIDTH 1
++ #define TX_IPFIL27_PORT0_EN_LBN 54
++ #define TX_IPFIL27_PORT0_EN_WIDTH 1
++ #define TX_IPFIL26_PORT1_EN_LBN 53
++ #define TX_IPFIL26_PORT1_EN_WIDTH 1
++ #define TX_IPFIL26_PORT0_EN_LBN 52
++ #define TX_IPFIL26_PORT0_EN_WIDTH 1
++ #define TX_IPFIL25_PORT1_EN_LBN 51
++ #define TX_IPFIL25_PORT1_EN_WIDTH 1
++ #define TX_IPFIL25_PORT0_EN_LBN 50
++ #define TX_IPFIL25_PORT0_EN_WIDTH 1
++ #define TX_IPFIL24_PORT1_EN_LBN 49
++ #define TX_IPFIL24_PORT1_EN_WIDTH 1
++ #define TX_IPFIL24_PORT0_EN_LBN 48
++ #define TX_IPFIL24_PORT0_EN_WIDTH 1
++ #define TX_IPFIL23_PORT1_EN_LBN 47
++ #define TX_IPFIL23_PORT1_EN_WIDTH 1
++ #define TX_IPFIL23_PORT0_EN_LBN 46
++ #define TX_IPFIL23_PORT0_EN_WIDTH 1
++ #define TX_IPFIL22_PORT1_EN_LBN 45
++ #define TX_IPFIL22_PORT1_EN_WIDTH 1
++ #define TX_IPFIL22_PORT0_EN_LBN 44
++ #define TX_IPFIL22_PORT0_EN_WIDTH 1
++ #define TX_IPFIL21_PORT1_EN_LBN 43
++ #define TX_IPFIL21_PORT1_EN_WIDTH 1
++ #define TX_IPFIL21_PORT0_EN_LBN 42
++ #define TX_IPFIL21_PORT0_EN_WIDTH 1
++ #define TX_IPFIL20_PORT1_EN_LBN 41
++ #define TX_IPFIL20_PORT1_EN_WIDTH 1
++ #define TX_IPFIL20_PORT0_EN_LBN 40
++ #define TX_IPFIL20_PORT0_EN_WIDTH 1
++ #define TX_IPFIL19_PORT1_EN_LBN 39
++ #define TX_IPFIL19_PORT1_EN_WIDTH 1
++ #define TX_IPFIL19_PORT0_EN_LBN 38
++ #define TX_IPFIL19_PORT0_EN_WIDTH 1
++ #define TX_IPFIL18_PORT1_EN_LBN 37
++ #define TX_IPFIL18_PORT1_EN_WIDTH 1
++ #define TX_IPFIL18_PORT0_EN_LBN 36
++ #define TX_IPFIL18_PORT0_EN_WIDTH 1
++ #define TX_IPFIL17_PORT1_EN_LBN 35
++ #define TX_IPFIL17_PORT1_EN_WIDTH 1
++ #define TX_IPFIL17_PORT0_EN_LBN 34
++ #define TX_IPFIL17_PORT0_EN_WIDTH 1
++ #define TX_IPFIL16_PORT1_EN_LBN 33
++ #define TX_IPFIL16_PORT1_EN_WIDTH 1
++ #define TX_IPFIL16_PORT0_EN_LBN 32
++ #define TX_IPFIL16_PORT0_EN_WIDTH 1
++ #define TX_IPFIL15_PORT1_EN_LBN 31
++ #define TX_IPFIL15_PORT1_EN_WIDTH 1
++ #define TX_IPFIL15_PORT0_EN_LBN 30
++ #define TX_IPFIL15_PORT0_EN_WIDTH 1
++ #define TX_IPFIL14_PORT1_EN_LBN 29
++ #define TX_IPFIL14_PORT1_EN_WIDTH 1
++ #define TX_IPFIL14_PORT0_EN_LBN 28
++ #define TX_IPFIL14_PORT0_EN_WIDTH 1
++ #define TX_IPFIL13_PORT1_EN_LBN 27
++ #define TX_IPFIL13_PORT1_EN_WIDTH 1
++ #define TX_IPFIL13_PORT0_EN_LBN 26
++ #define TX_IPFIL13_PORT0_EN_WIDTH 1
++ #define TX_IPFIL12_PORT1_EN_LBN 25
++ #define TX_IPFIL12_PORT1_EN_WIDTH 1
++ #define TX_IPFIL12_PORT0_EN_LBN 24
++ #define TX_IPFIL12_PORT0_EN_WIDTH 1
++ #define TX_IPFIL11_PORT1_EN_LBN 23
++ #define TX_IPFIL11_PORT1_EN_WIDTH 1
++ #define TX_IPFIL11_PORT0_EN_LBN 22
++ #define TX_IPFIL11_PORT0_EN_WIDTH 1
++ #define TX_IPFIL10_PORT1_EN_LBN 21
++ #define TX_IPFIL10_PORT1_EN_WIDTH 1
++ #define TX_IPFIL10_PORT0_EN_LBN 20
++ #define TX_IPFIL10_PORT0_EN_WIDTH 1
++ #define TX_IPFIL9_PORT1_EN_LBN 19
++ #define TX_IPFIL9_PORT1_EN_WIDTH 1
++ #define TX_IPFIL9_PORT0_EN_LBN 18
++ #define TX_IPFIL9_PORT0_EN_WIDTH 1
++ #define TX_IPFIL8_PORT1_EN_LBN 17
++ #define TX_IPFIL8_PORT1_EN_WIDTH 1
++ #define TX_IPFIL8_PORT0_EN_LBN 16
++ #define TX_IPFIL8_PORT0_EN_WIDTH 1
++ #define TX_IPFIL7_PORT1_EN_LBN 15
++ #define TX_IPFIL7_PORT1_EN_WIDTH 1
++ #define TX_IPFIL7_PORT0_EN_LBN 14
++ #define TX_IPFIL7_PORT0_EN_WIDTH 1
++ #define TX_IPFIL6_PORT1_EN_LBN 13
++ #define TX_IPFIL6_PORT1_EN_WIDTH 1
++ #define TX_IPFIL6_PORT0_EN_LBN 12
++ #define TX_IPFIL6_PORT0_EN_WIDTH 1
++ #define TX_IPFIL5_PORT1_EN_LBN 11
++ #define TX_IPFIL5_PORT1_EN_WIDTH 1
++ #define TX_IPFIL5_PORT0_EN_LBN 10
++ #define TX_IPFIL5_PORT0_EN_WIDTH 1
++ #define TX_IPFIL4_PORT1_EN_LBN 9
++ #define TX_IPFIL4_PORT1_EN_WIDTH 1
++ #define TX_IPFIL4_PORT0_EN_LBN 8
++ #define TX_IPFIL4_PORT0_EN_WIDTH 1
++ #define TX_IPFIL3_PORT1_EN_LBN 7
++ #define TX_IPFIL3_PORT1_EN_WIDTH 1
++ #define TX_IPFIL3_PORT0_EN_LBN 6
++ #define TX_IPFIL3_PORT0_EN_WIDTH 1
++ #define TX_IPFIL2_PORT1_EN_LBN 5
++ #define TX_IPFIL2_PORT1_EN_WIDTH 1
++ #define TX_IPFIL2_PORT0_EN_LBN 4
++ #define TX_IPFIL2_PORT0_EN_WIDTH 1
++ #define TX_IPFIL1_PORT1_EN_LBN 3
++ #define TX_IPFIL1_PORT1_EN_WIDTH 1
++ #define TX_IPFIL1_PORT0_EN_LBN 2
++ #define TX_IPFIL1_PORT0_EN_WIDTH 1
++ #define TX_IPFIL0_PORT1_EN_LBN 1
++ #define TX_IPFIL0_PORT1_EN_WIDTH 1
++ #define TX_IPFIL0_PORT0_EN_LBN 0
++ #define TX_IPFIL0_PORT0_EN_WIDTH 1
++#define TX_IPFIL_TBL_OFST 0xB00 // Transmit IP source address filter table
++ #define TX_IPFIL_MASK_LBN 32
++ #define TX_IPFIL_MASK_WIDTH 32
++ #define TX_IP_SRC_ADR_LBN 0
++ #define TX_IP_SRC_ADR_WIDTH 32
++#define TX_PACE_REG_A1_OFST 0xF80000 // Transmit pace control register
++#define TX_PACE_REG_B0_OFST 0xA90 // Transmit pace control register
++ #define TX_PACE_SB_AF_LBN 19
++ #define TX_PACE_SB_AF_WIDTH 10
++ #define TX_PACE_SB_NOTAF_LBN 9
++ #define TX_PACE_SB_NOTAF_WIDTH 10
++ #define TX_PACE_FB_BASE_LBN 5
++ #define TX_PACE_FB_BASE_WIDTH 4
++ #define TX_PACE_BIN_TH_LBN 0
++ #define TX_PACE_BIN_TH_WIDTH 5
++#define TX_PACE_TBL_A1_OFST 0xF80040 // Transmit pacing table
++#define TX_PACE_TBL_FIRST_QUEUE_A1 4
++#define TX_PACE_TBL_B0_OFST 0xF80000 // Transmit pacing table
++#define TX_PACE_TBL_FIRST_QUEUE_B0 0
++ #define TX_PACE_LBN 0
++ #define TX_PACE_WIDTH 5
++
++//////////////---- EE/Flash Registers C Header ----//////////////
++#define EE_SPI_HCMD_REG_KER_OFST 0x100 // SPI host command register
++#define EE_SPI_HCMD_REG_OFST 0x100 // SPI host command register
++ #define EE_SPI_HCMD_CMD_EN_LBN 31
++ #define EE_SPI_HCMD_CMD_EN_WIDTH 1
++ #define EE_WR_TIMER_ACTIVE_LBN 28
++ #define EE_WR_TIMER_ACTIVE_WIDTH 1
++ #define EE_SPI_HCMD_SF_SEL_LBN 24
++ #define EE_SPI_HCMD_SF_SEL_WIDTH 1
++ #define EE_SPI_HCMD_DABCNT_LBN 16
++ #define EE_SPI_HCMD_DABCNT_WIDTH 5
++ #define EE_SPI_HCMD_READ_LBN 15
++ #define EE_SPI_HCMD_READ_WIDTH 1
++ #define EE_SPI_HCMD_DUBCNT_LBN 12
++ #define EE_SPI_HCMD_DUBCNT_WIDTH 2
++ #define EE_SPI_HCMD_ADBCNT_LBN 8
++ #define EE_SPI_HCMD_ADBCNT_WIDTH 2
++ #define EE_SPI_HCMD_ENC_LBN 0
++ #define EE_SPI_HCMD_ENC_WIDTH 8
++#define EE_SPI_HADR_REG_KER_OFST 0X110 // SPI host address register
++#define EE_SPI_HADR_REG_OFST 0X110 // SPI host address register
++ #define EE_SPI_HADR_DUBYTE_LBN 24
++ #define EE_SPI_HADR_DUBYTE_WIDTH 8
++ #define EE_SPI_HADR_ADR_LBN 0
++ #define EE_SPI_HADR_ADR_WIDTH 24
++#define EE_SPI_HDATA_REG_KER_OFST 0x120 // SPI host data register
++#define EE_SPI_HDATA_REG_OFST 0x120 // SPI host data register
++ #define EE_SPI_HDATA3_LBN 96
++ #define EE_SPI_HDATA3_WIDTH 32
++ #define EE_SPI_HDATA2_LBN 64
++ #define EE_SPI_HDATA2_WIDTH 32
++ #define EE_SPI_HDATA1_LBN 32
++ #define EE_SPI_HDATA1_WIDTH 32
++ #define EE_SPI_HDATA0_LBN 0
++ #define EE_SPI_HDATA0_WIDTH 32
++#define EE_BASE_PAGE_REG_KER_OFST 0x130 // Expansion ROM base mirror register
++#define EE_BASE_PAGE_REG_OFST 0x130 // Expansion ROM base mirror register
++ #define EE_EXP_ROM_WINDOW_BASE_LBN 16
++ #define EE_EXP_ROM_WINDOW_BASE_WIDTH 13
++ #define EE_EXPROM_MASK_LBN 0
++ #define EE_EXPROM_MASK_WIDTH 13
++#define EE_VPD_CFG0_REG_KER_OFST 0X140 // SPI/VPD configuration register
++#define EE_VPD_CFG0_REG_OFST 0X140 // SPI/VPD configuration register
++ #define EE_SF_FASTRD_EN_LBN 127
++ #define EE_SF_FASTRD_EN_WIDTH 1
++ #define EE_SF_CLOCK_DIV_LBN 120
++ #define EE_SF_CLOCK_DIV_WIDTH 7
++ #define EE_VPD_WIP_POLL_LBN 119
++ #define EE_VPD_WIP_POLL_WIDTH 1
++ #define EE_VPDW_LENGTH_LBN 80
++ #define EE_VPDW_LENGTH_WIDTH 15
++ #define EE_VPDW_BASE_LBN 64
++ #define EE_VPDW_BASE_WIDTH 15
++ #define EE_VPD_WR_CMD_EN_LBN 56
++ #define EE_VPD_WR_CMD_EN_WIDTH 8
++ #define EE_VPD_BASE_LBN 32
++ #define EE_VPD_BASE_WIDTH 24
++ #define EE_VPD_LENGTH_LBN 16
++ #define EE_VPD_LENGTH_WIDTH 13
++ #define EE_VPD_AD_SIZE_LBN 8
++ #define EE_VPD_AD_SIZE_WIDTH 5
++ #define EE_VPD_ACCESS_ON_LBN 5
++ #define EE_VPD_ACCESS_ON_WIDTH 1
++#define EE_VPD_SW_CNTL_REG_KER_OFST 0X150 // VPD access SW control register
++#define EE_VPD_SW_CNTL_REG_OFST 0X150 // VPD access SW control register
++ #define EE_VPD_CYCLE_PENDING_LBN 31
++ #define EE_VPD_CYCLE_PENDING_WIDTH 1
++ #define EE_VPD_CYC_WRITE_LBN 28
++ #define EE_VPD_CYC_WRITE_WIDTH 1
++ #define EE_VPD_CYC_ADR_LBN 0
++ #define EE_VPD_CYC_ADR_WIDTH 15
++#define EE_VPD_SW_DATA_REG_KER_OFST 0x160 // VPD access SW data register
++#define EE_VPD_SW_DATA_REG_OFST 0x160 // VPD access SW data register
++ #define EE_VPD_CYC_DAT_LBN 0
++ #define EE_VPD_CYC_DAT_WIDTH 32
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_falcon_desc.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_falcon_desc.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_falcon_desc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_falcon_desc.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,43 @@
++//////////////---- Descriptors C Headers ----//////////////
++// Receive Kernel IP Descriptor
++ #define RX_KER_BUF_SIZE_LBN 48
++ #define RX_KER_BUF_SIZE_WIDTH 14
++ #define RX_KER_BUF_REGION_LBN 46
++ #define RX_KER_BUF_REGION_WIDTH 2
++ #define RX_KER_BUF_REGION0_DECODE 0
++ #define RX_KER_BUF_REGION1_DECODE 1
++ #define RX_KER_BUF_REGION2_DECODE 2
++ #define RX_KER_BUF_REGION3_DECODE 3
++ #define RX_KER_BUF_ADR_LBN 0
++ #define RX_KER_BUF_ADR_WIDTH 46
++// Receive User IP Descriptor
++ #define RX_USR_2BYTE_OFS_LBN 20
++ #define RX_USR_2BYTE_OFS_WIDTH 12
++ #define RX_USR_BUF_ID_LBN 0
++ #define RX_USR_BUF_ID_WIDTH 20
++// Transmit Kernel IP Descriptor
++ #define TX_KER_PORT_LBN 63
++ #define TX_KER_PORT_WIDTH 1
++ #define TX_KER_CONT_LBN 62
++ #define TX_KER_CONT_WIDTH 1
++ #define TX_KER_BYTE_CNT_LBN 48
++ #define TX_KER_BYTE_CNT_WIDTH 14
++ #define TX_KER_BUF_REGION_LBN 46
++ #define TX_KER_BUF_REGION_WIDTH 2
++ #define TX_KER_BUF_REGION0_DECODE 0
++ #define TX_KER_BUF_REGION1_DECODE 1
++ #define TX_KER_BUF_REGION2_DECODE 2
++ #define TX_KER_BUF_REGION3_DECODE 3
++ #define TX_KER_BUF_ADR_LBN 0
++ #define TX_KER_BUF_ADR_WIDTH 46
++// Transmit User IP Descriptor
++ #define TX_USR_PORT_LBN 47
++ #define TX_USR_PORT_WIDTH 1
++ #define TX_USR_CONT_LBN 46
++ #define TX_USR_CONT_WIDTH 1
++ #define TX_USR_BYTE_CNT_LBN 33
++ #define TX_USR_BYTE_CNT_WIDTH 13
++ #define TX_USR_BUF_ID_LBN 13
++ #define TX_USR_BUF_ID_WIDTH 20
++ #define TX_USR_BYTE_OFS_LBN 0
++ #define TX_USR_BYTE_OFS_WIDTH 13
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_falcon_event.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_falcon_event.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_falcon_event.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_falcon_event.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,123 @@
++//////////////---- Events Format C Header ----//////////////
++//////////////---- Event entry ----//////////////
++ #define EV_CODE_LBN 60
++ #define EV_CODE_WIDTH 4
++ #define RX_IP_EV_DECODE 0
++ #define TX_IP_EV_DECODE 2
++ #define DRIVER_EV_DECODE 5
++ #define GLOBAL_EV_DECODE 6
++ #define DRV_GEN_EV_DECODE 7
++ #define EV_DATA_LBN 0
++ #define EV_DATA_WIDTH 60
++//////////////---- Receive IP events for both Kernel & User event queues ----//////////////
++ #define RX_EV_PKT_OK_LBN 56
++ #define RX_EV_PKT_OK_WIDTH 1
++ #define RX_EV_BUF_OWNER_ID_ERR_LBN 54
++ #define RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++ #define RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
++ #define RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
++ #define RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
++ #define RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
++ #define RX_EV_ETH_CRC_ERR_LBN 50
++ #define RX_EV_ETH_CRC_ERR_WIDTH 1
++ #define RX_EV_FRM_TRUNC_LBN 49
++ #define RX_EV_FRM_TRUNC_WIDTH 1
++ #define RX_EV_DRIB_NIB_LBN 48
++ #define RX_EV_DRIB_NIB_WIDTH 1
++ #define RX_EV_TOBE_DISC_LBN 47
++ #define RX_EV_TOBE_DISC_WIDTH 1
++ #define RX_EV_PKT_TYPE_LBN 44
++ #define RX_EV_PKT_TYPE_WIDTH 3
++ #define RX_EV_PKT_TYPE_ETH_DECODE 0
++ #define RX_EV_PKT_TYPE_LLC_DECODE 1
++ #define RX_EV_PKT_TYPE_JUMBO_DECODE 2
++ #define RX_EV_PKT_TYPE_VLAN_DECODE 3
++ #define RX_EV_PKT_TYPE_VLAN_LLC_DECODE 4
++ #define RX_EV_PKT_TYPE_VLAN_JUMBO_DECODE 5
++ #define RX_EV_HDR_TYPE_LBN 42
++ #define RX_EV_HDR_TYPE_WIDTH 2
++ #define RX_EV_HDR_TYPE_TCP_IPV4_DECODE 0
++ #define RX_EV_HDR_TYPE_UDP_IPV4_DECODE 1
++ #define RX_EV_HDR_TYPE_OTHER_IP_DECODE 2
++ #define RX_EV_HDR_TYPE_NON_IP_DECODE 3
++ #define RX_EV_DESC_Q_EMPTY_LBN 41
++ #define RX_EV_DESC_Q_EMPTY_WIDTH 1
++ #define RX_EV_MCAST_HASH_MATCH_LBN 40
++ #define RX_EV_MCAST_HASH_MATCH_WIDTH 1
++ #define RX_EV_MCAST_PKT_LBN 39
++ #define RX_EV_MCAST_PKT_WIDTH 1
++ #define RX_EV_Q_LABEL_LBN 32
++ #define RX_EV_Q_LABEL_WIDTH 5
++ #define RX_JUMBO_CONT_LBN 31
++ #define RX_JUMBO_CONT_WIDTH 1
++ #define RX_SOP_LBN 15
++ #define RX_SOP_WIDTH 1
++ #define RX_PORT_LBN 30
++ #define RX_PORT_WIDTH 1
++ #define RX_EV_BYTE_CNT_LBN 16
++ #define RX_EV_BYTE_CNT_WIDTH 14
++ #define RX_iSCSI_PKT_OK_LBN 14
++ #define RX_iSCSI_PKT_OK_WIDTH 1
++ #define RX_ISCSI_DDIG_ERR_LBN 13
++ #define RX_ISCSI_DDIG_ERR_WIDTH 1
++ #define RX_ISCSI_HDIG_ERR_LBN 12
++ #define RX_ISCSI_HDIG_ERR_WIDTH 1
++ #define RX_EV_DESC_PTR_LBN 0
++ #define RX_EV_DESC_PTR_WIDTH 12
++//////////////---- Transmit IP events for both Kernel & User event queues ----//////////////
++ #define TX_EV_PKT_ERR_LBN 38
++ #define TX_EV_PKT_ERR_WIDTH 1
++ #define TX_EV_PKT_TOO_BIG_LBN 37
++ #define TX_EV_PKT_TOO_BIG_WIDTH 1
++ #define TX_EV_Q_LABEL_LBN 32
++ #define TX_EV_Q_LABEL_WIDTH 5
++ #define TX_EV_PORT_LBN 16
++ #define TX_EV_PORT_WIDTH 1
++ #define TX_EV_WQ_FF_FULL_LBN 15
++ #define TX_EV_WQ_FF_FULL_WIDTH 1
++ #define TX_EV_BUF_OWNER_ID_ERR_LBN 14
++ #define TX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++ #define TX_EV_COMP_LBN 12
++ #define TX_EV_COMP_WIDTH 1
++ #define TX_EV_DESC_PTR_LBN 0
++ #define TX_EV_DESC_PTR_WIDTH 12
++//////////////---- Char or Kernel driver events ----//////////////
++ #define DRIVER_EV_SUB_CODE_LBN 56
++ #define DRIVER_EV_SUB_CODE_WIDTH 4
++ #define TX_DESCQ_FLS_DONE_EV_DECODE 0x0
++ #define RX_DESCQ_FLS_DONE_EV_DECODE 0x1
++ #define EVQ_INIT_DONE_EV_DECODE 0x2
++ #define EVQ_NOT_EN_EV_DECODE 0x3
++ #define RX_DESCQ_FLSFF_OVFL_EV_DECODE 0x4
++ #define SRM_UPD_DONE_EV_DECODE 0x5
++ #define WAKE_UP_EV_DECODE 0x6
++ #define TX_PKT_NON_TCP_UDP_DECODE 0x9
++ #define TIMER_EV_DECODE 0xA
++ #define RX_DSC_ERROR_EV_DECODE 0xE
++ #define DRIVER_EV_TX_DESCQ_ID_LBN 0
++ #define DRIVER_EV_TX_DESCQ_ID_WIDTH 12
++ #define DRIVER_EV_RX_DESCQ_ID_LBN 0
++ #define DRIVER_EV_RX_DESCQ_ID_WIDTH 12
++ #define DRIVER_EV_EVQ_ID_LBN 0
++ #define DRIVER_EV_EVQ_ID_WIDTH 12
++ #define DRIVER_TMR_ID_LBN 0
++ #define DRIVER_TMR_ID_WIDTH 12
++ #define DRIVER_EV_SRM_UPD_LBN 0
++ #define DRIVER_EV_SRM_UPD_WIDTH 2
++ #define SRM_CLR_EV_DECODE 0
++ #define SRM_UPD_EV_DECODE 1
++ #define SRM_ILLCLR_EV_DECODE 2
++//////////////---- Global events. Sent to both event queue 0 and 4. ----//////////////
++ #define XFP_PHY_INTR_LBN 10
++ #define XFP_PHY_INTR_WIDTH 1
++ #define XG_PHY_INTR_LBN 9
++ #define XG_PHY_INTR_WIDTH 1
++ #define G_PHY1_INTR_LBN 8
++ #define G_PHY1_INTR_WIDTH 1
++ #define G_PHY0_INTR_LBN 7
++ #define G_PHY0_INTR_WIDTH 1
++//////////////---- Driver generated events ----//////////////
++ #define DRV_GEN_EV_CODE_LBN 60
++ #define DRV_GEN_EV_CODE_WIDTH 4
++ #define DRV_GEN_EV_DATA_LBN 0
++ #define DRV_GEN_EV_DATA_WIDTH 60
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_falcon.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_falcon.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_falcon.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_falcon.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,172 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author slp
++ * \brief Falcon specific definitions
++ * \date 2004/08
++ */
++
++#ifndef __EF_VI_FALCON_H__
++#define __EF_VI_FALCON_H__
++
++#define EFHW_4K 0x00001000u
++#define EFHW_8K 0x00002000u
++
++/* include the autogenerated register definitions */
++
++#include "ef_vi_falcon_core.h"
++#include "ef_vi_falcon_desc.h"
++#include "ef_vi_falcon_event.h"
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Helpers to turn bit shifts into dword shifts and check that the bit fields
++ * haven't overflown the dword etc. Aim is to preserve consistency with the
++ * autogenerated headers - once stable we could hard code.
++ *
++ *---------------------------------------------------------------------------*/
++
++/* mask constructors */
++#define __FALCON_MASK(WIDTH,T) ((((T)1) << (WIDTH)) - 1)
++#define __EFVI_MASK32(WIDTH) __FALCON_MASK((WIDTH),uint32_t)
++#define __EFVI_MASK64(WIDTH) __FALCON_MASK((WIDTH),uint64_t)
++
++#define __EFVI_FALCON_MASKFIELD32(LBN, WIDTH) ((uint32_t) \
++ (__EFVI_MASK32(WIDTH) << (LBN)))
++
++/* constructors for fields which span the first and second dwords */
++#define __LW(LBN) (32 - LBN)
++#define LOW(v, LBN, WIDTH) ((uint32_t) \
++ (((v) & __EFVI_MASK64(__LW((LBN)))) << (LBN)))
++#define HIGH(v, LBN, WIDTH) ((uint32_t)(((v) >> __LW((LBN))) & \
++ __EFVI_MASK64((WIDTH - __LW((LBN))))))
++/* constructors for fields within the second dword */
++#define __DW2(LBN) ((LBN) - 32)
++
++/* constructors for fields which span the second and third dwords */
++#define __LW2(LBN) (64 - LBN)
++#define LOW2(v, LBN, WIDTH) ((uint32_t) \
++ (((v) & __EFVI_MASK64(__LW2((LBN)))) << ((LBN) - 32)))
++#define HIGH2(v, LBN, WIDTH) ((uint32_t) \
++ (((v) >> __LW2((LBN))) & __EFVI_MASK64((WIDTH - __LW2((LBN))))))
++
++/* constructors for fields within the third dword */
++#define __DW3(LBN) ((LBN) - 64)
++
++
++/* constructors for fields which span the third and fourth dwords */
++#define __LW3(LBN) (96 - LBN)
++#define LOW3(v, LBN, WIDTH) ((uint32_t) \
++ (((v) & __EFVI_MASK64(__LW3((LBN)))) << ((LBN) - 64)))
++#define HIGH3(v, LBN, WIDTH) ((unit32_t) \
++ (((v) >> __LW3((LBN))) & __EFVI_MASK64((WIDTH - __LW3((LBN))))))
++
++/* constructors for fields within the fourth dword */
++#define __DW4(LBN) ((LBN) - 96)
++
++/* checks that the autogenerated headers our consistent with our model */
++#define WIDTHCHCK(a, b) ef_assert((a) == (b))
++#define RANGECHCK(v, WIDTH) \
++ ef_assert(((uint64_t)(v) & ~(__EFVI_MASK64((WIDTH)))) == 0)
++
++/* fields within the first dword */
++#define DWCHCK(LBN, WIDTH) ef_assert(((LBN) >= 0) &&(((LBN)+(WIDTH)) <= 32))
++
++/* fields which span the first and second dwords */
++#define LWCHK(LBN, WIDTH) ef_assert(WIDTH >= __LW(LBN))
++
++/*----------------------------------------------------------------------------
++ *
++ * Buffer virtual addresses (4K buffers)
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Form a buffer virtual address from buffer ID and offset. If the offset
++** is larger than the buffer size, then the buffer indexed will be
++** calculated appropriately. It is the responsibility of the caller to
++** ensure that they have valid buffers programmed at that address.
++*/
++#define EFVI_FALCON_VADDR_4K_S (12)
++#define EFVI_FALCON_VADDR_M 0xfffff /* post shift mask */
++
++
++#define EFVI_FALCON_BUFFER_4K_ADDR(id,off) \
++ (((id) << EFVI_FALCON_VADDR_4K_S) + (off))
++
++#define EFVI_FALCON_BUFFER_4K_PAGE(vaddr) \
++ (((vaddr) >> EFVI_FALCON_VADDR_4K_S) & EFVI_FALCON_VADDR_M)
++
++#define EFVI_FALCON_BUFFER_4K_OFF(vaddr) \
++ ((vaddr) & __EFVI_MASK32(EFVI_FALCON_VADDR_4K_S))
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Masks
++ *
++ *---------------------------------------------------------------------------*/
++
++#define EFVI_FALCON_CLOCK_ASIC_HZ (125000)
++#define EFVI_FALCON_CLOCK_FPGA_HZ (62500)
++#define EFVI_FALCON_CLOCK_HZ EFVI_FALCON_CLOCK_ASIC_HZ
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Timers
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Event-Queue Timer granularity - measured in us
++ Given by: 4096 * 3 cycle * clock period */
++
++#define EFVI_FALCON_EVQTIMER_PERIOD_US ((4096 * 3 * 1000) / EFVI_FALCON_CLOCK_HZ)
++
++/* mode bits */
++#define EFVI_FALCON_TIMER_MODE_DIS 0 /* disabled */
++#define EFVI_FALCON_TIMER_MODE_RUN 1 /* started counting right away */
++#define EFVI_FALCON_TIMER_MODE_HOLD 2 /* trigger mode (user queues) */
++
++#define EFVI_FALCON_EVQTIMER_HOLD (EFVI_FALCON_TIMER_MODE_HOLD << TIMER_MODE_LBN)
++#define EFVI_FALCON_EVQTIMER_RUN (EFVI_FALCON_TIMER_MODE_RUN << TIMER_MODE_LBN)
++#define EFVI_FALCON_EVQTIMER_DISABLE (EFVI_FALCON_TIMER_MODE_DIS << TIMER_MODE_LBN)
++
++
++/* ---- efhw_event_t helpers --- */
++
++#define EFVI_FALCON_EVENT_CODE(evp) \
++ ((evp)->u64 & EFVI_FALCON_EVENT_CODE_MASK)
++
++#define EFVI_FALCON_EVENT_SW_DATA_MASK 0x0000ffff
++
++#define __EFVI_FALCON_OPEN_MASK(WIDTH) ((((uint64_t)1) << (WIDTH)) - 1)
++
++#define EFVI_FALCON_EVENT_CODE_MASK \
++ (__EFVI_FALCON_OPEN_MASK(EV_CODE_WIDTH) << EV_CODE_LBN)
++
++
++#endif /* __EF_VI_FALCON_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_internal.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_internal.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/ef_vi_internal.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/ef_vi_internal.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,256 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr
++ * \brief Really-and-truely-honestly internal stuff for libef.
++ * \date 2004/06/13
++ */
++
++/*! \cidoxg_include_ci_ul */
++#ifndef __CI_EF_VI_INTERNAL_H__
++#define __CI_EF_VI_INTERNAL_H__
++
++
++/* These flags share space with enum ef_vi_flags. */
++#define EF_VI_BUG5692_WORKAROUND 0x10000
++
++
++/* ***********************************************************************
++ * COMPILATION CONTROL FLAGS (see ef_vi.h for "workaround" controls)
++ */
++
++#define EF_VI_DO_MAGIC_CHECKS 1
++
++
++/**********************************************************************
++ * Headers
++ */
++
++#include <etherfabric/ef_vi.h>
++#include "sysdep.h"
++#include "ef_vi_falcon.h"
++
++
++/**********************************************************************
++ * Debugging.
++ */
++
++#ifndef NDEBUG
++
++# define _ef_assert(exp, file, line) BUG_ON(!(exp));
++
++# define _ef_assert2(exp, x, y, file, line) do { \
++ if (unlikely(!(exp))) \
++ BUG(); \
++ } while (0)
++
++#else
++
++# define _ef_assert(exp, file, line)
++# define _ef_assert2(e, x, y, file, line)
++
++#endif
++
++#define ef_assert(a) do{ _ef_assert((a),__FILE__,__LINE__); } while(0)
++#define ef_assert_equal(a,b) _ef_assert2((a)==(b),(a),(b),__FILE__,__LINE__)
++#define ef_assert_eq ef_assert_equal
++#define ef_assert_lt(a,b) _ef_assert2((a)<(b),(a),(b),__FILE__,__LINE__)
++#define ef_assert_le(a,b) _ef_assert2((a)<=(b),(a),(b),__FILE__,__LINE__)
++#define ef_assert_nequal(a,b) _ef_assert2((a)!=(b),(a),(b),__FILE__,__LINE__)
++#define ef_assert_ne ef_assert_nequal
++#define ef_assert_ge(a,b) _ef_assert2((a)>=(b),(a),(b),__FILE__,__LINE__)
++#define ef_assert_gt(a,b) _ef_assert2((a)>(b),(a),(b),__FILE__,__LINE__)
++
++/**********************************************************************
++ * Debug checks. ******************************************************
++ **********************************************************************/
++
++#ifdef NDEBUG
++# define EF_VI_MAGIC_SET(p, type)
++# define EF_VI_CHECK_VI(p)
++# define EF_VI_CHECK_EVENT_Q(p)
++# define EF_VI_CHECK_IOBUFSET(p)
++# define EF_VI_CHECK_FILTER(p)
++# define EF_VI_CHECK_SHMBUF(p)
++# define EF_VI_CHECK_PT_EP(p)
++#else
++# define EF_VI 0x3
++# define EF_EPLOCK 0x6
++# define EF_IOBUFSET 0x9
++# define EF_FILTER 0xa
++# define EF_SHMBUF 0x11
++
++# define EF_VI_MAGIC(p, type) \
++ (((unsigned)(type) << 28) | \
++ (((unsigned)(intptr_t)(p)) & 0x0fffffffu))
++
++# if !EF_VI_DO_MAGIC_CHECKS
++# define EF_VI_MAGIC_SET(p, type)
++# define EF_VI_MAGIC_CHECK(p, type)
++# else
++# define EF_VI_MAGIC_SET(p, type) \
++ do { \
++ (p)->magic = EF_VI_MAGIC((p), (type)); \
++ } while (0)
++
++# define EF_VI_MAGIC_OKAY(p, type) \
++ ((p)->magic == EF_VI_MAGIC((p), (type)))
++
++# define EF_VI_MAGIC_CHECK(p, type) \
++ ef_assert(EF_VI_MAGIC_OKAY((p), (type)))
++
++#endif /* EF_VI_DO_MAGIC_CHECKS */
++
++# define EF_VI_CHECK_VI(p) \
++ ef_assert(p); \
++ EF_VI_MAGIC_CHECK((p), EF_VI);
++
++# define EF_VI_CHECK_EVENT_Q(p) \
++ ef_assert(p); \
++ EF_VI_MAGIC_CHECK((p), EF_VI); \
++ ef_assert((p)->evq_base); \
++ ef_assert((p)->evq_mask);
++
++# define EF_VI_CHECK_PT_EP(p) \
++ ef_assert(p); \
++ EF_VI_MAGIC_CHECK((p), EF_VI); \
++ ef_assert((p)->ep_state);
++
++# define EF_VI_CHECK_IOBUFSET(p) \
++ ef_assert(p); \
++ EF_VI_MAGIC_CHECK((p), EF_IOBUFSET)
++
++# define EF_VI_CHECK_FILTER(p) \
++ ef_assert(p); \
++ EF_VI_MAGIC_CHECK((p), EF_FILTER);
++
++# define EF_VI_CHECK_SHMBUF(p) \
++ ef_assert(p); \
++ EF_VI_MAGIC_CHECK((p), EF_SHMBUF);
++
++#endif
++
++#ifndef NDEBUG
++# define EF_DRIVER_MAGIC 0x00f00ba4
++# define EF_ASSERT_THIS_DRIVER_VALID(driver) \
++ do{ ef_assert(driver); \
++ EF_VI_MAGIC_CHECK((driver), EF_DRIVER_MAGIC); \
++ ef_assert((driver)->init); }while(0)
++
++# define EF_ASSERT_DRIVER_VALID() EF_ASSERT_THIS_DRIVER_VALID(&ci_driver)
++#else
++# define EF_ASSERT_THIS_DRIVER_VALID(driver)
++# define EF_ASSERT_DRIVER_VALID()
++#endif
++
++
++/* *************************************
++ * Power of 2 FIFO
++ */
++
++#define EF_VI_FIFO2_M(f, x) ((x) & ((f)->fifo_mask))
++#define ef_vi_fifo2_valid(f) ((f) && (f)->fifo && (f)->fifo_mask > 0 && \
++ (f)->fifo_rd_i <= (f)->fifo_mask && \
++ (f)->fifo_wr_i <= (f)->fifo_mask && \
++ EF_VI_IS_POW2((f)->fifo_mask+1u))
++
++#define ef_vi_fifo2_init(f, cap) \
++ do{ ef_assert(EF_VI_IS_POW2((cap) + 1)); \
++ (f)->fifo_rd_i = (f)->fifo_wr_i = 0u; \
++ (f)->fifo_mask = (cap); \
++ }while(0)
++
++#define ef_vi_fifo2_is_empty(f) ((f)->fifo_rd_i == (f)->fifo_wr_i)
++#define ef_vi_fifo2_capacity(f) ((f)->fifo_mask)
++#define ef_vi_fifo2_buf_size(f) ((f)->fifo_mask + 1u)
++#define ef_vi_fifo2_end(f) ((f)->fifo + ef_vi_fifo2_buf_size(f))
++#define ef_vi_fifo2_peek(f) ((f)->fifo[(f)->fifo_rd_i])
++#define ef_vi_fifo2_poke(f) ((f)->fifo[(f)->fifo_wr_i])
++#define ef_vi_fifo2_num(f) EF_VI_FIFO2_M((f),(f)->fifo_wr_i-(f)->fifo_rd_i)
++
++#define ef_vi_fifo2_wr_prev(f) \
++ do{ (f)->fifo_wr_i = EF_VI_FIFO2_M((f), (f)->fifo_wr_i - 1u); }while(0)
++#define ef_vi_fifo2_wr_next(f) \
++ do{ (f)->fifo_wr_i = EF_VI_FIFO2_M((f), (f)->fifo_wr_i + 1u); }while(0)
++#define ef_vi_fifo2_rd_adv(f, n) \
++ do{ (f)->fifo_rd_i = EF_VI_FIFO2_M((f), (f)->fifo_rd_i + (n)); }while(0)
++#define ef_vi_fifo2_rd_prev(f) \
++ do{ (f)->fifo_rd_i = EF_VI_FIFO2_M((f), (f)->fifo_rd_i - 1u); }while(0)
++#define ef_vi_fifo2_rd_next(f) \
++ do{ (f)->fifo_rd_i = EF_VI_FIFO2_M((f), (f)->fifo_rd_i + 1u); }while(0)
++
++#define ef_vi_fifo2_put(f, v) \
++ do{ ef_vi_fifo2_poke(f) = (v); ef_vi_fifo2_wr_next(f); }while(0)
++#define ef_vi_fifo2_get(f, pv) \
++ do{ *(pv) = ef_vi_fifo2_peek(f); ef_vi_fifo2_rd_next(f); }while(0)
++
++
++/* *********************************************************************
++ * Eventq handling
++ */
++
++typedef union {
++ uint64_t u64;
++ struct {
++ uint32_t a;
++ uint32_t b;
++ } opaque;
++} ef_vi_event;
++
++
++#define EF_VI_EVENT_OFFSET(q, i) \
++ (((q)->evq_state->evq_ptr - (i) * sizeof(ef_vi_event)) & (q)->evq_mask)
++
++#define EF_VI_EVENT_PTR(q, i) \
++ ((ef_vi_event*) ((q)->evq_base + EF_VI_EVENT_OFFSET((q), (i))))
++
++/* *********************************************************************
++ * Miscellaneous goodies
++ */
++#ifdef NDEBUG
++# define EF_VI_DEBUG(x)
++#else
++# define EF_VI_DEBUG(x) x
++#endif
++
++#define EF_VI_ROUND_UP(i, align) (((i)+(align)-1u) & ~((align)-1u))
++#define EF_VI_ALIGN_FWD(p, align) (((p)+(align)-1u) & ~((align)-1u))
++#define EF_VI_ALIGN_BACK(p, align) ((p) & ~((align)-1u))
++#define EF_VI_PTR_ALIGN_BACK(p, align) \
++ ((char*)EF_VI_ALIGN_BACK(((intptr_t)(p)), ((intptr_t)(align))))
++#define EF_VI_IS_POW2(x) ((x) && ! ((x) & ((x) - 1)))
++
++
++/* ********************************************************************
++ */
++
++extern void falcon_vi_init(ef_vi*, void* vvis ) EF_VI_HF;
++extern void ef_eventq_state_init(ef_vi* evq) EF_VI_HF;
++extern void __ef_init(void) EF_VI_HF;
++
++
++#endif /* __CI_EF_VI_INTERNAL_H__ */
++
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/etherfabric/ef_vi.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/etherfabric/ef_vi.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/etherfabric/ef_vi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/etherfabric/ef_vi.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,665 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \brief Virtual Interface
++ * \date 2007/05/16
++ */
++
++#ifndef __EFAB_EF_VI_H__
++#define __EFAB_EF_VI_H__
++
++
++/**********************************************************************
++ * Primitive types ****************************************************
++ **********************************************************************/
++
++/* We standardise on the types from stdint.h and synthesise these types
++ * for compilers/platforms that don't provide them */
++
++# include <linux/types.h>
++# define EF_VI_ALIGN(x) __attribute__ ((aligned (x)))
++# define ef_vi_inline static inline
++
++
++
++/**********************************************************************
++ * Types **************************************************************
++ **********************************************************************/
++
++typedef uint32_t ef_eventq_ptr;
++
++typedef uint64_t ef_addr;
++typedef char* ef_vi_ioaddr_t;
++
++/**********************************************************************
++ * ef_event ***********************************************************
++ **********************************************************************/
++
++/*! \i_ef_vi A DMA request identifier.
++**
++** This is an integer token specified by the transport and associated
++** with a DMA request. It is returned to the VI user with DMA completion
++** events. It is typically used to identify the buffer associated with
++** the transfer.
++*/
++typedef int ef_request_id;
++
++typedef union {
++ uint64_t u64[1];
++ uint32_t u32[2];
++} ef_vi_qword;
++
++typedef ef_vi_qword ef_hw_event;
++
++#define EF_REQUEST_ID_BITS 16u
++#define EF_REQUEST_ID_MASK ((1u << EF_REQUEST_ID_BITS) - 1u)
++
++/*! \i_ef_event An [ef_event] is a token that identifies something that
++** has happened. Examples include packets received, packets transmitted
++** and errors.
++*/
++typedef union {
++ struct {
++ ef_hw_event ev;
++ unsigned type :16;
++ } generic;
++ struct {
++ ef_hw_event ev;
++ unsigned type :16;
++ /*ef_request_id request_id :EF_REQUEST_ID_BITS;*/
++ unsigned q_id :16;
++ unsigned len :16;
++ unsigned flags :16;
++ } rx;
++ struct { /* This *must* have same layout as [rx]. */
++ ef_hw_event ev;
++ unsigned type :16;
++ /*ef_request_id request_id :EF_REQUEST_ID_BITS;*/
++ unsigned q_id :16;
++ unsigned len :16;
++ unsigned flags :16;
++ unsigned subtype :16;
++ } rx_discard;
++ struct {
++ ef_hw_event ev;
++ unsigned type :16;
++ /*ef_request_id request_id :EF_REQUEST_ID_BITS;*/
++ unsigned q_id :16;
++ } tx;
++ struct {
++ ef_hw_event ev;
++ unsigned type :16;
++ /*ef_request_id request_id :EF_REQUEST_ID_BITS;*/
++ unsigned q_id :16;
++ unsigned subtype :16;
++ } tx_error;
++ struct {
++ ef_hw_event ev;
++ unsigned type :16;
++ unsigned q_id :16;
++ } rx_no_desc_trunc;
++ struct {
++ ef_hw_event ev;
++ unsigned type :16;
++ unsigned data;
++ } sw;
++} ef_event;
++
++
++#define EF_EVENT_TYPE(e) ((e).generic.type)
++enum {
++ /** Good data was received. */
++ EF_EVENT_TYPE_RX,
++ /** Packets have been sent. */
++ EF_EVENT_TYPE_TX,
++ /** Data received and buffer consumed, but something is wrong. */
++ EF_EVENT_TYPE_RX_DISCARD,
++ /** Transmit of packet failed. */
++ EF_EVENT_TYPE_TX_ERROR,
++ /** Received packet was truncated due to lack of descriptors. */
++ EF_EVENT_TYPE_RX_NO_DESC_TRUNC,
++ /** Software generated event. */
++ EF_EVENT_TYPE_SW,
++ /** Event queue overflow. */
++ EF_EVENT_TYPE_OFLOW,
++};
++
++#define EF_EVENT_RX_BYTES(e) ((e).rx.len)
++#define EF_EVENT_RX_Q_ID(e) ((e).rx.q_id)
++#define EF_EVENT_RX_CONT(e) ((e).rx.flags & EF_EVENT_FLAG_CONT)
++#define EF_EVENT_RX_SOP(e) ((e).rx.flags & EF_EVENT_FLAG_SOP)
++#define EF_EVENT_RX_ISCSI_OKAY(e) ((e).rx.flags & EF_EVENT_FLAG_ISCSI_OK)
++#define EF_EVENT_FLAG_SOP 0x1
++#define EF_EVENT_FLAG_CONT 0x2
++#define EF_EVENT_FLAG_ISCSI_OK 0x4
++
++#define EF_EVENT_TX_Q_ID(e) ((e).tx.q_id)
++
++#define EF_EVENT_RX_DISCARD_Q_ID(e) ((e).rx_discard.q_id)
++#define EF_EVENT_RX_DISCARD_LEN(e) ((e).rx_discard.len)
++#define EF_EVENT_RX_DISCARD_TYPE(e) ((e).rx_discard.subtype)
++enum {
++ EF_EVENT_RX_DISCARD_CSUM_BAD,
++ EF_EVENT_RX_DISCARD_CRC_BAD,
++ EF_EVENT_RX_DISCARD_TRUNC,
++ EF_EVENT_RX_DISCARD_RIGHTS,
++ EF_EVENT_RX_DISCARD_OTHER,
++};
++
++#define EF_EVENT_TX_ERROR_Q_ID(e) ((e).tx_error.q_id)
++#define EF_EVENT_TX_ERROR_TYPE(e) ((e).tx_error.subtype)
++enum {
++ EF_EVENT_TX_ERROR_RIGHTS,
++ EF_EVENT_TX_ERROR_OFLOW,
++ EF_EVENT_TX_ERROR_2BIG,
++ EF_EVENT_TX_ERROR_BUS,
++};
++
++#define EF_EVENT_RX_NO_DESC_TRUNC_Q_ID(e) ((e).rx_no_desc_trunc.q_id)
++
++#define EF_EVENT_SW_DATA_MASK 0xffff
++#define EF_EVENT_SW_DATA(e) ((e).sw.data)
++
++#define EF_EVENT_FMT "[ev:%x:%08x:%08x]"
++#define EF_EVENT_PRI_ARG(e) (unsigned) (e).generic.type, \
++ (unsigned) (e).generic.ev.u32[1], \
++ (unsigned) (e).generic.ev.u32[0]
++
++#define EF_GET_HW_EV(e) ((e).generic.ev)
++#define EF_GET_HW_EV_PTR(e) (&(e).generic.ev)
++#define EF_GET_HW_EV_U64(e) ((e).generic.ev.u64[0])
++
++
++/* ***************** */
++
++/*! Used by netif shared state. Must use types of explicit size. */
++typedef struct {
++ uint16_t rx_last_desc_ptr; /* for RX duplicates */
++ uint8_t bad_sop; /* bad SOP detected */
++ uint8_t frag_num; /* next fragment #, 0=>SOP */
++} ef_rx_dup_state_t;
++
++
++/* Max number of ports on any SF NIC. */
++#define EFAB_DMAQS_PER_EVQ_MAX 32
++
++typedef struct {
++ ef_eventq_ptr evq_ptr;
++ int32_t trashed;
++ ef_rx_dup_state_t rx_dup_state[EFAB_DMAQS_PER_EVQ_MAX];
++} ef_eventq_state;
++
++
++/*! \i_ef_base [ef_iovec] is similar the standard [struct iovec]. An
++** array of these is used to designate a scatter/gather list of I/O
++** buffers.
++*/
++typedef struct {
++ ef_addr iov_base EF_VI_ALIGN(8);
++ unsigned iov_len;
++} ef_iovec;
++
++/* Falcon constants */
++#define TX_EV_DESC_PTR_LBN 0
++
++/**********************************************************************
++ * ef_iobufset ********************************************************
++ **********************************************************************/
++
++/*! \i_ef_bufs An [ef_iobufset] is a collection of buffers to be used
++** with the NIC.
++*/
++typedef struct ef_iobufset {
++ unsigned magic;
++ unsigned bufs_mmap_bytes;
++ unsigned bufs_handle;
++ int bufs_ptr_off;
++ ef_addr bufs_addr;
++ unsigned bufs_size; /* size rounded to pow2 */
++ int bufs_num;
++ int faultonaccess;
++} ef_iobufset;
++
++
++/**********************************************************************
++ * ef_vi **************************************************************
++ **********************************************************************/
++
++enum ef_vi_flags {
++ EF_VI_RX_SCATTER = 0x1,
++ EF_VI_ISCSI_RX_HDIG = 0x2,
++ EF_VI_ISCSI_TX_HDIG = 0x4,
++ EF_VI_ISCSI_RX_DDIG = 0x8,
++ EF_VI_ISCSI_TX_DDIG = 0x10,
++ EF_VI_TX_PHYS_ADDR = 0x20,
++ EF_VI_RX_PHYS_ADDR = 0x40,
++ EF_VI_TX_IP_CSUM_DIS = 0x80,
++ EF_VI_TX_TCPUDP_CSUM_DIS= 0x100,
++ EF_VI_TX_TCPUDP_ONLY = 0x200,
++ /* Flags in range 0xXXXX0000 are for internal use. */
++};
++
++typedef struct {
++ uint32_t added;
++ uint32_t removed;
++} ef_vi_txq_state;
++
++typedef struct {
++ uint32_t added;
++ uint32_t removed;
++} ef_vi_rxq_state;
++
++typedef struct {
++ uint32_t mask;
++ void* doorbell;
++ void* descriptors;
++ uint16_t* ids;
++ unsigned misalign_mask;
++} ef_vi_txq;
++
++typedef struct {
++ uint32_t mask;
++ void* doorbell;
++ void* descriptors;
++ uint16_t* ids;
++} ef_vi_rxq;
++
++typedef struct {
++ ef_eventq_state evq;
++ ef_vi_txq_state txq;
++ ef_vi_rxq_state rxq;
++ /* Followed by request id fifos. */
++} ef_vi_state;
++
++/*! \i_ef_vi A virtual interface.
++**
++** An [ef_vi] represents a virtual interface on a specific NIC. A
++** virtual interface is a collection of an event queue and two DMA queues
++** used to pass Ethernet frames between the transport implementation and
++** the network.
++*/
++typedef struct ef_vi {
++ unsigned magic;
++
++ unsigned vi_resource_id;
++ unsigned vi_resource_handle_hack;
++ unsigned vi_i;
++
++ char* vi_mem_mmap_ptr;
++ int vi_mem_mmap_bytes;
++ char* vi_io_mmap_ptr;
++ int vi_io_mmap_bytes;
++
++ ef_eventq_state* evq_state;
++ char* evq_base;
++ unsigned evq_mask;
++ ef_vi_ioaddr_t evq_timer_reg;
++
++ ef_vi_txq vi_txq;
++ ef_vi_rxq vi_rxq;
++ ef_vi_state* ep_state;
++ enum ef_vi_flags vi_flags;
++} ef_vi;
++
++
++enum ef_vi_arch {
++ EF_VI_ARCH_FALCON,
++};
++
++
++struct ef_vi_nic_type {
++ unsigned char arch;
++ char variant;
++ unsigned char revision;
++};
++
++
++/* This structure is opaque to the client & used to pass mapping data
++ * from the resource manager to the ef_vi lib. for ef_vi_init().
++ */
++struct vi_mappings {
++ uint32_t signature;
++# define VI_MAPPING_VERSION 0x02 /*Byte: Increment me if struct altered*/
++# define VI_MAPPING_SIGNATURE (0xBA1150 + VI_MAPPING_VERSION)
++
++ struct ef_vi_nic_type nic_type;
++
++ int vi_instance;
++
++ unsigned evq_bytes;
++ char* evq_base;
++ ef_vi_ioaddr_t evq_timer_reg;
++
++ unsigned rx_queue_capacity;
++ ef_vi_ioaddr_t rx_dma_ef1;
++ char* rx_dma_falcon;
++ ef_vi_ioaddr_t rx_bell;
++
++ unsigned tx_queue_capacity;
++ ef_vi_ioaddr_t tx_dma_ef1;
++ char* tx_dma_falcon;
++ ef_vi_ioaddr_t tx_bell;
++};
++/* This is used by clients to allocate a suitably sized buffer for the
++ * resource manager to fill & ef_vi_init() to use. */
++#define VI_MAPPINGS_SIZE (sizeof(struct vi_mappings))
++
++
++/**********************************************************************
++ * ef_config **********************************************************
++ **********************************************************************/
++
++struct ef_config_t {
++ int log; /* debug logging level */
++};
++
++extern struct ef_config_t ef_config;
++
++
++/**********************************************************************
++ * ef_vi **************************************************************
++ **********************************************************************/
++
++/* Initialise [data_area] with information required to initialise an ef_vi.
++ * In the following, an unused param should be set to NULL. Note the case
++ * marked (*) of [iobuf_mmap] for falcon/driver; for normal driver this
++ * must be NULL.
++ *
++ * \param data_area [in,out] required, must ref at least VI_MAPPINGS_SIZE
++ * bytes
++ * \param evq_capacity [in] number of events in event queue. Specify 0 for
++ * no event queue.
++ * \param rxq_capacity [in] number of descriptors in RX DMA queue. Specify
++ * 0 for no RX queue.
++ * \param txq_capacity [in] number of descriptors in TX DMA queue. Specify
++ * 0 for no TX queue.
++ * \param mmap_info [in] mem-map info for resource
++ * \param io_mmap [in] ef1, required
++ * falcon, required
++ * \param iobuf_mmap [in] ef1, UL: unused
++ * falcon, UL: required
++ */
++extern void ef_vi_init_mapping_vi(void* data_area, struct ef_vi_nic_type,
++ unsigned rxq_capacity,
++ unsigned txq_capacity, int instance,
++ void* io_mmap, void* iobuf_mmap_rx,
++ void* iobuf_mmap_tx, enum ef_vi_flags);
++
++
++extern void ef_vi_init_mapping_evq(void* data_area, struct ef_vi_nic_type,
++ int instance, unsigned evq_bytes,
++ void* base, void* timer_reg);
++
++ef_vi_inline unsigned ef_vi_resource_id(ef_vi* vi)
++{
++ return vi->vi_resource_id;
++}
++
++ef_vi_inline enum ef_vi_flags ef_vi_flags(ef_vi* vi)
++{
++ return vi->vi_flags;
++}
++
++
++/**********************************************************************
++ * Receive interface **************************************************
++ **********************************************************************/
++
++/*! \i_ef_vi Returns the amount of space in the RX descriptor ring.
++**
++** \return the amount of space in the queue.
++*/
++ef_vi_inline int ef_vi_receive_space(ef_vi* vi)
++{
++ ef_vi_rxq_state* qs = &vi->ep_state->rxq;
++ return vi->vi_rxq.mask - (qs->added - qs->removed);
++}
++
++
++/*! \i_ef_vi Returns the fill level of the RX descriptor ring.
++**
++** \return the fill level of the queue.
++*/
++ef_vi_inline int ef_vi_receive_fill_level(ef_vi* vi)
++{
++ ef_vi_rxq_state* qs = &vi->ep_state->rxq;
++ return qs->added - qs->removed;
++}
++
++
++ef_vi_inline int ef_vi_receive_capacity(ef_vi* vi)
++{
++ return vi->vi_rxq.mask;
++}
++
++/*! \i_ef_vi Complete a receive operation.
++**
++** When a receive completion event is received, it should be passed to
++** this function. The request-id for the buffer that the packet was
++** delivered to is returned.
++**
++** After this function returns, more space may be available in the
++** receive queue.
++*/
++extern ef_request_id ef_vi_receive_done(const ef_vi*, const ef_event*);
++
++/*! \i_ef_vi Return request ID indicated by a receive event
++ */
++ef_vi_inline ef_request_id ef_vi_receive_request_id(const ef_vi* vi,
++ const ef_event* ef_ev)
++{
++ const ef_vi_qword* ev = EF_GET_HW_EV_PTR(*ef_ev);
++ return ev->u32[0] & vi->vi_rxq.mask;
++}
++
++
++/*! \i_ef_vi Form a receive descriptor.
++**
++** If \c initial_rx_bytes is zero use a reception size at least as large
++** as an MTU.
++*/
++extern int ef_vi_receive_init(ef_vi* vi, ef_addr addr, ef_request_id dma_id,
++ int intial_rx_bytes);
++
++/*! \i_ef_vi Submit initialised receive descriptors to the NIC. */
++extern void ef_vi_receive_push(ef_vi* vi);
++
++/*! \i_ef_vi Post a buffer on the receive queue.
++**
++** \return 0 on success, or -EAGAIN if the receive queue is full
++*/
++extern int ef_vi_receive_post(ef_vi*, ef_addr addr,
++ ef_request_id dma_id);
++
++/**********************************************************************
++ * Transmit interface *************************************************
++ **********************************************************************/
++
++/*! \i_ef_vi Return the amount of space (in descriptors) in the transmit
++** queue.
++**
++** \return the amount of space in the queue (in descriptors)
++*/
++ef_vi_inline int ef_vi_transmit_space(ef_vi* vi)
++{
++ ef_vi_txq_state* qs = &vi->ep_state->txq;
++ return vi->vi_txq.mask - (qs->added - qs->removed);
++}
++
++
++/*! \i_ef_vi Returns the fill level of the TX descriptor ring.
++**
++** \return the fill level of the queue.
++*/
++ef_vi_inline int ef_vi_transmit_fill_level(ef_vi* vi)
++{
++ ef_vi_txq_state* qs = &vi->ep_state->txq;
++ return qs->added - qs->removed;
++}
++
++
++/*! \i_ef_vi Returns the total capacity of the TX descriptor ring.
++**
++** \return the capacity of the queue.
++*/
++ef_vi_inline int ef_vi_transmit_capacity(ef_vi* vi)
++{
++ return vi->vi_txq.mask;
++}
++
++
++/*! \i_ef_vi Transmit a packet.
++**
++** \param bytes must be greater than ETH_ZLEN.
++** \return -EAGAIN if the transmit queue is full, or 0 on success
++*/
++extern int ef_vi_transmit(ef_vi*, ef_addr, int bytes, ef_request_id dma_id);
++
++/*! \i_ef_vi Transmit a packet using a gather list.
++**
++** \param iov_len must be greater than zero
++** \param iov the first must be non-zero in length (but others need not)
++**
++** \return -EAGAIN if the queue is full, or 0 on success
++*/
++extern int ef_vi_transmitv(ef_vi*, const ef_iovec* iov, int iov_len,
++ ef_request_id dma_id);
++
++/*! \i_ef_vi Initialise a DMA request.
++**
++** \return -EAGAIN if the queue is full, or 0 on success
++*/
++extern int ef_vi_transmit_init(ef_vi*, ef_addr, int bytes,
++ ef_request_id dma_id);
++
++/*! \i_ef_vi Initialise a DMA request.
++**
++** \return -EAGAIN if the queue is full, or 0 on success
++*/
++extern int ef_vi_transmitv_init(ef_vi*, const ef_iovec*, int iov_len,
++ ef_request_id dma_id);
++
++/*! \i_ef_vi Submit DMA requests to the NIC.
++**
++** The DMA requests must have been initialised using
++** ef_vi_transmit_init() or ef_vi_transmitv_init().
++*/
++extern void ef_vi_transmit_push(ef_vi*);
++
++
++/*! \i_ef_vi Maximum number of transmit completions per transmit event. */
++#define EF_VI_TRANSMIT_BATCH 64
++
++/*! \i_ef_vi Determine the set of [ef_request_id]s for each DMA request
++** which has been completed by a given transmit completion
++** event.
++**
++** \param ids must point to an array of length EF_VI_TRANSMIT_BATCH
++** \return the number of valid [ef_request_id]s (can be zero)
++*/
++extern int ef_vi_transmit_unbundle(ef_vi* ep, const ef_event*,
++ ef_request_id* ids);
++
++
++/*! \i_ef_event Returns true if ef_eventq_poll() will return event(s). */
++extern int ef_eventq_has_event(ef_vi* vi);
++
++/*! \i_ef_event Returns true if there are quite a few events in the event
++** queue.
++**
++** This looks ahead in the event queue, so has the property that it will
++** not ping-pong a cache-line when it is called concurrently with events
++** being delivered.
++*/
++extern int ef_eventq_has_many_events(ef_vi* evq, int look_ahead);
++
++/*! Type of function to handle unknown events arriving on event queue
++** Return CI_TRUE iff the event has been handled.
++*/
++typedef int/*bool*/ ef_event_handler_fn(void* priv, ef_vi* evq, ef_event* ev);
++
++/*! Standard poll exception routine */
++extern int/*bool*/ ef_eventq_poll_exception(void* priv, ef_vi* evq,
++ ef_event* ev);
++
++/*! \i_ef_event Retrieve events from the event queue, handle RX/TX events
++** and pass any others to an exception handler function
++**
++** \return The number of events retrieved.
++*/
++extern int ef_eventq_poll_evs(ef_vi* evq, ef_event* evs, int evs_len,
++ ef_event_handler_fn *exception, void *expt_priv);
++
++/*! \i_ef_event Retrieve events from the event queue.
++**
++** \return The number of events retrieved.
++*/
++ef_vi_inline int ef_eventq_poll(ef_vi* evq, ef_event* evs, int evs_len)
++{
++ return ef_eventq_poll_evs(evq, evs, evs_len,
++ &ef_eventq_poll_exception, (void*)0);
++}
++
++/*! \i_ef_event Returns the capacity of an event queue. */
++ef_vi_inline int ef_eventq_capacity(ef_vi* vi)
++{
++ return (vi->evq_mask + 1u) / sizeof(ef_hw_event);
++}
++
++/* Returns the instance ID of [vi] */
++ef_vi_inline unsigned ef_vi_instance(ef_vi* vi)
++{ return vi->vi_i; }
++
++
++/**********************************************************************
++ * Initialisation *****************************************************
++ **********************************************************************/
++
++/*! Return size of state buffer of an initialised VI. */
++extern int ef_vi_state_bytes(ef_vi*);
++
++/*! Return size of buffer needed for VI state given sizes of RX and TX
++** DMA queues. Queue sizes must be legal sizes (power of 2), or 0 (no
++** queue).
++*/
++extern int ef_vi_calc_state_bytes(int rxq_size, int txq_size);
++
++/*! Initialise [ef_vi] from the provided resources. [vvis] must have been
++** created by ef_make_vi_data() & remains owned by the caller.
++*/
++extern void ef_vi_init(ef_vi*, void* vi_info, ef_vi_state* state,
++ ef_eventq_state* evq_state, enum ef_vi_flags);
++
++extern void ef_vi_state_init(ef_vi*);
++extern void ef_eventq_state_init(ef_vi*);
++
++/*! Convert an efhw device arch to ef_vi_arch, or returns -1 if not
++** recognised.
++*/
++extern int ef_vi_arch_from_efhw_arch(int efhw_arch);
++
++
++#endif /* __EFAB_EF_VI_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/falcon_event.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/falcon_event.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/falcon_event.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/falcon_event.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,346 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr
++ * \brief Routine to poll event queues.
++ * \date 2003/03/04
++ */
++
++/*! \cidoxg_lib_ef */
++#include "ef_vi_internal.h"
++
++/* Be worried about this on byteswapped machines */
++/* Due to crazy chipsets, we see the event words being written in
++** arbitrary order (bug4539). So test for presence of event must ensure
++** that both halves have changed from the null.
++*/
++# define EF_VI_IS_EVENT(evp) \
++ ( (((evp)->opaque.a != (uint32_t)-1) && \
++ ((evp)->opaque.b != (uint32_t)-1)) )
++
++
++#ifdef NDEBUG
++# define IS_DEBUG 0
++#else
++# define IS_DEBUG 1
++#endif
++
++
++/*! Check for RX events with inconsistent SOP/CONT
++**
++** Returns true if this event should be discarded
++*/
++ef_vi_inline int ef_eventq_is_rx_sop_cont_bad_efab(ef_vi* vi,
++ const ef_vi_qword* ev)
++{
++ ef_rx_dup_state_t* rx_dup_state;
++ uint8_t* bad_sop;
++
++ unsigned label = QWORD_GET_U(RX_EV_Q_LABEL, *ev);
++ unsigned sop = QWORD_TEST_BIT(RX_SOP, *ev);
++
++ ef_assert(vi);
++ ef_assert_lt(label, EFAB_DMAQS_PER_EVQ_MAX);
++
++ rx_dup_state = &vi->evq_state->rx_dup_state[label];
++ bad_sop = &rx_dup_state->bad_sop;
++
++ if( ! ((vi->vi_flags & EF_VI_BUG5692_WORKAROUND) || IS_DEBUG) ) {
++ *bad_sop = (*bad_sop && !sop);
++ }
++ else {
++ unsigned cont = QWORD_TEST_BIT(RX_JUMBO_CONT, *ev);
++ uint8_t *frag_num = &rx_dup_state->frag_num;
++
++ /* bad_sop should latch till the next sop */
++ *bad_sop = (*bad_sop && !sop) || ( !!sop != (*frag_num==0) );
++
++ /* we do not check the number of bytes relative to the
++ * fragment number and size of the user rx buffer here
++ * because we don't know the size of the user rx
++ * buffer - we probably should perform this check in
++ * the nearest code calling this though.
++ */
++ *frag_num = cont ? (*frag_num + 1) : 0;
++ }
++
++ return *bad_sop;
++}
++
++
++ef_vi_inline int falcon_rx_check_dup(ef_vi* evq, ef_event* ev_out,
++ const ef_vi_qword* ev)
++{
++ unsigned q_id = QWORD_GET_U(RX_EV_Q_LABEL, *ev);
++ unsigned desc_ptr = QWORD_GET_U(RX_EV_DESC_PTR, *ev);
++ ef_rx_dup_state_t* rx_dup_state = &evq->evq_state->rx_dup_state[q_id];
++
++ if(likely( desc_ptr != rx_dup_state->rx_last_desc_ptr )) {
++ rx_dup_state->rx_last_desc_ptr = desc_ptr;
++ return 0;
++ }
++
++ rx_dup_state->rx_last_desc_ptr = desc_ptr;
++ rx_dup_state->bad_sop = 1;
++#ifndef NDEBUG
++ rx_dup_state->frag_num = 0;
++#endif
++ BUG_ON(!QWORD_TEST_BIT(RX_EV_FRM_TRUNC, *ev));
++ BUG_ON( QWORD_TEST_BIT(RX_EV_PKT_OK, *ev));
++ BUG_ON(!QWORD_GET_U(RX_EV_BYTE_CNT, *ev) == 0);
++ ev_out->rx_no_desc_trunc.type = EF_EVENT_TYPE_RX_NO_DESC_TRUNC;
++ ev_out->rx_no_desc_trunc.q_id = q_id;
++ return 1;
++}
++
++
++ef_vi_inline void falcon_rx_event(ef_event* ev_out, const ef_vi_qword* ev)
++{
++ if(likely( QWORD_TEST_BIT(RX_EV_PKT_OK, *ev) )) {
++ ev_out->rx.type = EF_EVENT_TYPE_RX;
++ ev_out->rx.q_id = QWORD_GET_U(RX_EV_Q_LABEL, *ev);
++ ev_out->rx.len = QWORD_GET_U(RX_EV_BYTE_CNT, *ev);
++ if( QWORD_TEST_BIT(RX_SOP, *ev) )
++ ev_out->rx.flags = EF_EVENT_FLAG_SOP;
++ else
++ ev_out->rx.flags = 0;
++ if( QWORD_TEST_BIT(RX_JUMBO_CONT, *ev) )
++ ev_out->rx.flags |= EF_EVENT_FLAG_CONT;
++ if( QWORD_TEST_BIT(RX_iSCSI_PKT_OK, *ev) )
++ ev_out->rx.flags |= EF_EVENT_FLAG_ISCSI_OK;
++ }
++ else {
++ ev_out->rx_discard.type = EF_EVENT_TYPE_RX_DISCARD;
++ ev_out->rx_discard.q_id = QWORD_GET_U(RX_EV_Q_LABEL, *ev);
++ ev_out->rx_discard.len = QWORD_GET_U(RX_EV_BYTE_CNT, *ev);
++#if 1 /* hack for ptloop compatability: ?? TODO purge */
++ if( QWORD_TEST_BIT(RX_SOP, *ev) )
++ ev_out->rx_discard.flags = EF_EVENT_FLAG_SOP;
++ else
++ ev_out->rx_discard.flags = 0;
++ if( QWORD_TEST_BIT(RX_JUMBO_CONT, *ev) )
++ ev_out->rx_discard.flags |= EF_EVENT_FLAG_CONT;
++ if( QWORD_TEST_BIT(RX_iSCSI_PKT_OK, *ev) )
++ ev_out->rx_discard.flags |= EF_EVENT_FLAG_ISCSI_OK;
++#endif
++ /* Order matters here: more fundamental errors first. */
++ if( QWORD_TEST_BIT(RX_EV_BUF_OWNER_ID_ERR, *ev) )
++ ev_out->rx_discard.subtype =
++ EF_EVENT_RX_DISCARD_RIGHTS;
++ else if( QWORD_TEST_BIT(RX_EV_FRM_TRUNC, *ev) )
++ ev_out->rx_discard.subtype =
++ EF_EVENT_RX_DISCARD_TRUNC;
++ else if( QWORD_TEST_BIT(RX_EV_ETH_CRC_ERR, *ev) )
++ ev_out->rx_discard.subtype =
++ EF_EVENT_RX_DISCARD_CRC_BAD;
++ else if( QWORD_TEST_BIT(RX_EV_IP_HDR_CHKSUM_ERR, *ev) )
++ ev_out->rx_discard.subtype =
++ EF_EVENT_RX_DISCARD_CSUM_BAD;
++ else if( QWORD_TEST_BIT(RX_EV_TCP_UDP_CHKSUM_ERR, *ev) )
++ ev_out->rx_discard.subtype =
++ EF_EVENT_RX_DISCARD_CSUM_BAD;
++ else
++ ev_out->rx_discard.subtype =
++ EF_EVENT_RX_DISCARD_OTHER;
++ }
++}
++
++
++ef_vi_inline void falcon_tx_event(ef_event* ev_out, const ef_vi_qword* ev)
++{
++ /* Danger danger! No matter what we ask for wrt batching, we
++ ** will get a batched event every 16 descriptors, and we also
++ ** get dma-queue-empty events. i.e. Duplicates are expected.
++ **
++ ** In addition, if it's been requested in the descriptor, we
++ ** get an event per descriptor. (We don't currently request
++ ** this).
++ */
++ if(likely( QWORD_TEST_BIT(TX_EV_COMP, *ev) )) {
++ ev_out->tx.type = EF_EVENT_TYPE_TX;
++ ev_out->tx.q_id = QWORD_GET_U(TX_EV_Q_LABEL, *ev);
++ }
++ else {
++ ev_out->tx_error.type = EF_EVENT_TYPE_TX_ERROR;
++ ev_out->tx_error.q_id = QWORD_GET_U(TX_EV_Q_LABEL, *ev);
++ if(likely( QWORD_TEST_BIT(TX_EV_BUF_OWNER_ID_ERR, *ev) ))
++ ev_out->tx_error.subtype = EF_EVENT_TX_ERROR_RIGHTS;
++ else if(likely( QWORD_TEST_BIT(TX_EV_WQ_FF_FULL, *ev) ))
++ ev_out->tx_error.subtype = EF_EVENT_TX_ERROR_OFLOW;
++ else if(likely( QWORD_TEST_BIT(TX_EV_PKT_TOO_BIG, *ev) ))
++ ev_out->tx_error.subtype = EF_EVENT_TX_ERROR_2BIG;
++ else if(likely( QWORD_TEST_BIT(TX_EV_PKT_ERR, *ev) ))
++ ev_out->tx_error.subtype = EF_EVENT_TX_ERROR_BUS;
++ }
++}
++
++
++static void mark_bad(ef_event* ev)
++{
++ ev->generic.ev.u64[0] &=~ ((uint64_t) 1u << RX_EV_PKT_OK_LBN);
++}
++
++
++int ef_eventq_poll_evs(ef_vi* evq, ef_event* evs, int evs_len,
++ ef_event_handler_fn *exception, void *expt_priv)
++{
++ int evs_len_orig = evs_len;
++
++ EF_VI_CHECK_EVENT_Q(evq);
++ ef_assert(evs);
++ ef_assert_gt(evs_len, 0);
++
++ if(unlikely( EF_VI_IS_EVENT(EF_VI_EVENT_PTR(evq, 1)) ))
++ goto overflow;
++
++ do {
++ { /* Read the event out of the ring, then fiddle with
++ * copied version. Reason is that the ring is
++ * likely to get pushed out of cache by another
++ * event being delivered by hardware. */
++ ef_vi_event* ev = EF_VI_EVENT_PTR(evq, 0);
++ if( ! EF_VI_IS_EVENT(ev) )
++ break;
++ evs->generic.ev.u64[0] = cpu_to_le64 (ev->u64);
++ evq->evq_state->evq_ptr += sizeof(ef_vi_event);
++ ev->u64 = (uint64_t)(int64_t) -1;
++ }
++
++ /* Ugly: Exploit the fact that event code lies in top
++ * bits of event. */
++ ef_assert_ge(EV_CODE_LBN, 32u);
++ switch( evs->generic.ev.u32[1] >> (EV_CODE_LBN - 32u) ) {
++ case RX_IP_EV_DECODE:
++ /* Look for duplicate desc_ptr: it signals
++ * that a jumbo frame was truncated because we
++ * ran out of descriptors. */
++ if(unlikely( falcon_rx_check_dup
++ (evq, evs, &evs->generic.ev) )) {
++ --evs_len;
++ ++evs;
++ break;
++ }
++ else {
++ /* Cope with FalconA1 bugs where RX
++ * gives inconsistent RX events Mark
++ * events as bad until SOP becomes
++ * consistent again
++ * ef_eventq_is_rx_sop_cont_bad() has
++ * side effects - order is important
++ */
++ if(unlikely
++ (ef_eventq_is_rx_sop_cont_bad_efab
++ (evq, &evs->generic.ev) )) {
++ mark_bad(evs);
++ }
++ }
++ falcon_rx_event(evs, &evs->generic.ev);
++ --evs_len;
++ ++evs;
++ break;
++
++ case TX_IP_EV_DECODE:
++ falcon_tx_event(evs, &evs->generic.ev);
++ --evs_len;
++ ++evs;
++ break;
++
++ default:
++ break;
++ }
++ } while( evs_len );
++
++ return evs_len_orig - evs_len;
++
++
++ overflow:
++ evs->generic.type = EF_EVENT_TYPE_OFLOW;
++ evs->generic.ev.u64[0] = (uint64_t)((int64_t)-1);
++ return 1;
++}
++
++
++int/*bool*/ ef_eventq_poll_exception(void* priv, ef_vi* evq, ef_event* ev)
++{
++ int /*bool*/ handled = 0;
++
++ switch( ev->generic.ev.u32[1] >> (EV_CODE_LBN - 32u) ) {
++ case DRIVER_EV_DECODE:
++ if( QWORD_GET_U(DRIVER_EV_SUB_CODE, ev->generic.ev) ==
++ EVQ_INIT_DONE_EV_DECODE )
++ /* EVQ initialised event: ignore. */
++ handled = 1;
++ break;
++ }
++ return handled;
++}
++
++
++void ef_eventq_iterate(ef_vi* vi,
++ void (*fn)(void* arg, ef_vi*, int rel_pos,
++ int abs_pos, void* event),
++ void* arg, int stop_at_end)
++{
++ int i, size_evs = (vi->evq_mask + 1) / sizeof(ef_vi_event);
++
++ for( i = 0; i < size_evs; ++i ) {
++ ef_vi_event* e = EF_VI_EVENT_PTR(vi, -i);
++ if( EF_VI_IS_EVENT(e) )
++ fn(arg, vi, i,
++ EF_VI_EVENT_OFFSET(vi, -i) / sizeof(ef_vi_event),
++ e);
++ else if( stop_at_end )
++ break;
++ }
++}
++
++
++int ef_eventq_has_event(ef_vi* vi)
++{
++ return EF_VI_IS_EVENT(EF_VI_EVENT_PTR(vi, 0));
++}
++
++
++int ef_eventq_has_many_events(ef_vi* vi, int look_ahead)
++{
++ ef_assert_ge(look_ahead, 0);
++ return EF_VI_IS_EVENT(EF_VI_EVENT_PTR(vi, -look_ahead));
++}
++
++
++int ef_eventq_has_rx_event(ef_vi* vi)
++{
++ ef_vi_event* ev;
++ int i, n_evs = 0;
++
++ for( i = 0; EF_VI_IS_EVENT(EF_VI_EVENT_PTR(vi, i)); --i ) {
++ ev = EF_VI_EVENT_PTR(vi, i);
++ if( EFVI_FALCON_EVENT_CODE(ev) == EF_EVENT_TYPE_RX ) n_evs++;
++ }
++ return n_evs;
++}
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/falcon_vi.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/falcon_vi.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/falcon_vi.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/falcon_vi.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,465 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr, stg
++ * \brief Falcon-specific VI
++ * \date 2006/11/30
++ */
++
++#include "ef_vi_internal.h"
++
++
++#define EFVI_FALCON_DMA_TX_FRAG 1
++
++
++/* TX descriptor for both physical and virtual packet transfers */
++typedef union {
++ uint32_t dword[2];
++} ef_vi_falcon_dma_tx_buf_desc;
++typedef ef_vi_falcon_dma_tx_buf_desc ef_vi_falcon_dma_tx_phys_desc;
++
++
++/* RX descriptor for physical addressed transfers */
++typedef union {
++ uint32_t dword[2];
++} ef_vi_falcon_dma_rx_phys_desc;
++
++
++/* RX descriptor for virtual packet transfers */
++typedef struct {
++ uint32_t dword[1];
++} ef_vi_falcon_dma_rx_buf_desc;
++
++/* Buffer table index */
++typedef uint32_t ef_vi_buffer_addr_t;
++
++ef_vi_inline int64_t dma_addr_to_u46(int64_t src_dma_addr)
++{
++ return (src_dma_addr & __FALCON_MASK(46, int64_t));
++}
++
++/*! Setup a physical address based descriptor with a specified length */
++ef_vi_inline void
++__falcon_dma_rx_calc_ip_phys(ef_vi_dma_addr_t dest_pa,
++ ef_vi_falcon_dma_rx_phys_desc *desc,
++ int bytes)
++{
++ int region = 0; /* TODO fixme */
++ int64_t dest = dma_addr_to_u46(dest_pa); /* lower 46 bits */
++
++ DWCHCK(__DW2(RX_KER_BUF_SIZE_LBN), RX_KER_BUF_SIZE_WIDTH);
++ DWCHCK(__DW2(RX_KER_BUF_REGION_LBN),RX_KER_BUF_REGION_WIDTH);
++
++ LWCHK(RX_KER_BUF_ADR_LBN, RX_KER_BUF_ADR_WIDTH);
++
++ RANGECHCK(bytes, RX_KER_BUF_SIZE_WIDTH);
++ RANGECHCK(region, RX_KER_BUF_REGION_WIDTH);
++
++ ef_assert(desc);
++
++ desc->dword[1] = ((bytes << __DW2(RX_KER_BUF_SIZE_LBN)) |
++ (region << __DW2(RX_KER_BUF_REGION_LBN)) |
++ (HIGH(dest,
++ RX_KER_BUF_ADR_LBN,
++ RX_KER_BUF_ADR_WIDTH)));
++
++ desc->dword[0] = LOW(dest,
++ RX_KER_BUF_ADR_LBN,
++ RX_KER_BUF_ADR_WIDTH);
++}
++
++/*! Setup a virtual buffer descriptor for an IPMODE transfer */
++ef_vi_inline void
++__falcon_dma_tx_calc_ip_buf(unsigned buf_id, unsigned buf_ofs, unsigned bytes,
++ int port, int frag,
++ ef_vi_falcon_dma_tx_buf_desc *desc)
++{
++ DWCHCK(__DW2(TX_USR_PORT_LBN), TX_USR_PORT_WIDTH);
++ DWCHCK(__DW2(TX_USR_CONT_LBN), TX_USR_CONT_WIDTH);
++ DWCHCK(__DW2(TX_USR_BYTE_CNT_LBN), TX_USR_BYTE_CNT_WIDTH);
++ LWCHK(RX_KER_BUF_ADR_LBN, RX_KER_BUF_ADR_WIDTH);
++ DWCHCK(TX_USR_BYTE_OFS_LBN, TX_USR_BYTE_OFS_WIDTH);
++
++ RANGECHCK(bytes, TX_USR_BYTE_CNT_WIDTH);
++ RANGECHCK(port, TX_USR_PORT_WIDTH);
++ RANGECHCK(frag, TX_USR_CONT_WIDTH);
++ RANGECHCK(buf_id, TX_USR_BUF_ID_WIDTH);
++ RANGECHCK(buf_ofs, TX_USR_BYTE_OFS_WIDTH);
++
++ ef_assert(desc);
++
++ desc->dword[1] = ((port << __DW2(TX_USR_PORT_LBN)) |
++ (frag << __DW2(TX_USR_CONT_LBN)) |
++ (bytes << __DW2(TX_USR_BYTE_CNT_LBN)) |
++ (HIGH(buf_id,
++ TX_USR_BUF_ID_LBN,
++ TX_USR_BUF_ID_WIDTH)));
++
++ desc->dword[0] = ((LOW(buf_id,
++ TX_USR_BUF_ID_LBN,
++ (TX_USR_BUF_ID_WIDTH))) |
++ (buf_ofs << TX_USR_BYTE_OFS_LBN));
++}
++
++ef_vi_inline void
++falcon_dma_tx_calc_ip_buf_4k(unsigned buf_vaddr, unsigned bytes,
++ int port, int frag,
++ ef_vi_falcon_dma_tx_buf_desc *desc)
++{
++ /* TODO FIXME [buf_vaddr] consists of the buffer index in the
++ ** high bits, and an offset in the low bits. Assumptions
++ ** permate the code that these can be rolled into one 32bit
++ ** value, so this is currently preserved for Falcon. But we
++ ** should change to support 8K pages
++ */
++ unsigned buf_id = EFVI_FALCON_BUFFER_4K_PAGE(buf_vaddr);
++ unsigned buf_ofs = EFVI_FALCON_BUFFER_4K_OFF(buf_vaddr);
++
++ __falcon_dma_tx_calc_ip_buf( buf_id, buf_ofs, bytes, port, frag, desc);
++}
++
++ef_vi_inline void
++falcon_dma_tx_calc_ip_buf(unsigned buf_vaddr, unsigned bytes, int port,
++ int frag, ef_vi_falcon_dma_tx_buf_desc *desc)
++{
++ falcon_dma_tx_calc_ip_buf_4k(buf_vaddr, bytes, port, frag, desc);
++}
++
++/*! Setup a virtual buffer based descriptor */
++ef_vi_inline void
++__falcon_dma_rx_calc_ip_buf(unsigned buf_id, unsigned buf_ofs,
++ ef_vi_falcon_dma_rx_buf_desc *desc)
++{
++ /* check alignment of buffer offset and pack */
++ ef_assert((buf_ofs & 0x1) == 0);
++
++ buf_ofs >>= 1;
++
++ DWCHCK(RX_USR_2BYTE_OFS_LBN, RX_USR_2BYTE_OFS_WIDTH);
++ DWCHCK(RX_USR_BUF_ID_LBN, RX_USR_BUF_ID_WIDTH);
++
++ RANGECHCK(buf_ofs, RX_USR_2BYTE_OFS_WIDTH);
++ RANGECHCK(buf_id, RX_USR_BUF_ID_WIDTH);
++
++ ef_assert(desc);
++
++ desc->dword[0] = ((buf_ofs << RX_USR_2BYTE_OFS_LBN) |
++ (buf_id << RX_USR_BUF_ID_LBN));
++}
++
++ef_vi_inline void
++falcon_dma_rx_calc_ip_buf_4k(unsigned buf_vaddr,
++ ef_vi_falcon_dma_rx_buf_desc *desc)
++{
++ /* TODO FIXME [buf_vaddr] consists of the buffer index in the
++ ** high bits, and an offset in the low bits. Assumptions
++ ** permeate the code that these can be rolled into one 32bit
++ ** value, so this is currently preserved for Falcon. But we
++ ** should change to support 8K pages
++ */
++ unsigned buf_id = EFVI_FALCON_BUFFER_4K_PAGE(buf_vaddr);
++ unsigned buf_ofs = EFVI_FALCON_BUFFER_4K_OFF(buf_vaddr);
++
++ __falcon_dma_rx_calc_ip_buf(buf_id, buf_ofs, desc);
++}
++
++ef_vi_inline void
++falcon_dma_rx_calc_ip_buf(unsigned buf_vaddr,
++ ef_vi_falcon_dma_rx_buf_desc *desc)
++{
++ falcon_dma_rx_calc_ip_buf_4k(buf_vaddr, desc);
++}
++
++
++ef_vi_inline ef_vi_dma_addr_t ef_physaddr(ef_addr efaddr)
++{
++ return (ef_vi_dma_addr_t) efaddr;
++}
++
++
++/*! Convert between an ef_addr and a buffer table index
++** Assert that this was not a physical address
++*/
++ef_vi_inline ef_vi_buffer_addr_t ef_bufaddr(ef_addr efaddr)
++{
++ ef_assert(efaddr < ((uint64_t)1 << 32) );
++
++ return (ef_vi_buffer_addr_t) efaddr;
++}
++
++
++/*! Setup an physical address based descriptor for an IPMODE transfer */
++ef_vi_inline void
++falcon_dma_tx_calc_ip_phys(ef_vi_dma_addr_t src_dma_addr, unsigned bytes,
++ int port, int frag,
++ ef_vi_falcon_dma_tx_phys_desc *desc)
++{
++
++ int region = 0; /* FIXME */
++ int64_t src = dma_addr_to_u46(src_dma_addr); /* lower 46 bits */
++
++ DWCHCK(__DW2(TX_KER_PORT_LBN), TX_KER_PORT_WIDTH);
++ DWCHCK(__DW2(TX_KER_CONT_LBN), TX_KER_CONT_WIDTH);
++ DWCHCK(__DW2(TX_KER_BYTE_CNT_LBN), TX_KER_BYTE_CNT_WIDTH);
++ DWCHCK(__DW2(TX_KER_BUF_REGION_LBN),TX_KER_BUF_REGION_WIDTH);
++
++ LWCHK(TX_KER_BUF_ADR_LBN, TX_KER_BUF_ADR_WIDTH);
++
++ RANGECHCK(port, TX_KER_PORT_WIDTH);
++ RANGECHCK(frag, TX_KER_CONT_WIDTH);
++ RANGECHCK(bytes, TX_KER_BYTE_CNT_WIDTH);
++ RANGECHCK(region, TX_KER_BUF_REGION_WIDTH);
++
++ desc->dword[1] = ((port << __DW2(TX_KER_PORT_LBN)) |
++ (frag << __DW2(TX_KER_CONT_LBN)) |
++ (bytes << __DW2(TX_KER_BYTE_CNT_LBN)) |
++ (region << __DW2(TX_KER_BUF_REGION_LBN)) |
++ (HIGH(src,
++ TX_KER_BUF_ADR_LBN,
++ TX_KER_BUF_ADR_WIDTH)));
++
++ ef_assert_equal(TX_KER_BUF_ADR_LBN, 0);
++ desc->dword[0] = (uint32_t) src_dma_addr;
++}
++
++
++void falcon_vi_init(ef_vi* vi, void* vvis)
++{
++ struct vi_mappings *vm = (struct vi_mappings*)vvis;
++ uint16_t* ids;
++
++ ef_assert(vi);
++ ef_assert(vvis);
++ ef_assert_equal(vm->signature, VI_MAPPING_SIGNATURE);
++ ef_assert_equal(vm->nic_type.arch, EF_VI_ARCH_FALCON);
++
++ /* Initialise masks to zero, so that ef_vi_state_init() will
++ ** not do any harm when we don't have DMA queues. */
++ vi->vi_rxq.mask = vi->vi_txq.mask = 0;
++
++ /* Used for BUG5391_WORKAROUND. */
++ vi->vi_txq.misalign_mask = 0;
++
++ /* Initialise doorbell addresses to a distinctive small value
++ ** which will cause a segfault, to trap doorbell pushes to VIs
++ ** without DMA queues. */
++ vi->vi_rxq.doorbell = vi->vi_txq.doorbell = (ef_vi_ioaddr_t)0xdb;
++
++ ids = (uint16_t*) (vi->ep_state + 1);
++
++ if( vm->tx_queue_capacity ) {
++ vi->vi_txq.mask = vm->tx_queue_capacity - 1;
++ vi->vi_txq.doorbell = vm->tx_bell + 12;
++ vi->vi_txq.descriptors = vm->tx_dma_falcon;
++ vi->vi_txq.ids = ids;
++ ids += vi->vi_txq.mask + 1;
++ /* Check that the id fifo fits in the space allocated. */
++ ef_assert_le((char*) (vi->vi_txq.ids + vm->tx_queue_capacity),
++ (char*) vi->ep_state
++ + ef_vi_calc_state_bytes(vm->rx_queue_capacity,
++ vm->tx_queue_capacity));
++ }
++ if( vm->rx_queue_capacity ) {
++ vi->vi_rxq.mask = vm->rx_queue_capacity - 1;
++ vi->vi_rxq.doorbell = vm->rx_bell + 12;
++ vi->vi_rxq.descriptors = vm->rx_dma_falcon;
++ vi->vi_rxq.ids = ids;
++ /* Check that the id fifo fits in the space allocated. */
++ ef_assert_le((char*) (vi->vi_rxq.ids + vm->rx_queue_capacity),
++ (char*) vi->ep_state
++ + ef_vi_calc_state_bytes(vm->rx_queue_capacity,
++ vm->tx_queue_capacity));
++ }
++
++ if( vm->nic_type.variant == 'A' ) {
++ vi->vi_txq.misalign_mask = 15; /* BUG5391_WORKAROUND */
++ vi->vi_flags |= EF_VI_BUG5692_WORKAROUND;
++ }
++}
++
++
++int ef_vi_transmitv_init(ef_vi* vi, const ef_iovec* iov, int iov_len,
++ ef_request_id dma_id)
++{
++ ef_vi_txq* q = &vi->vi_txq;
++ ef_vi_txq_state* qs = &vi->ep_state->txq;
++ ef_vi_falcon_dma_tx_buf_desc* dp;
++ unsigned len, dma_len, di;
++ unsigned added_save = qs->added;
++ ef_addr dma_addr;
++ unsigned last_len = 0;
++
++ ef_assert(iov_len > 0);
++ ef_assert(iov);
++ ef_assert_equal((dma_id & EF_REQUEST_ID_MASK), dma_id);
++ ef_assert_nequal(dma_id, 0xffff);
++
++ dma_addr = iov->iov_base;
++ len = iov->iov_len;
++
++ if( vi->vi_flags & EF_VI_ISCSI_TX_DDIG ) {
++ /* Last 4 bytes of placeholder for digest must be
++ * removed for h/w */
++ ef_assert(len > 4);
++ last_len = iov[iov_len - 1].iov_len;
++ if( last_len <= 4 ) {
++ ef_assert(iov_len > 1);
++ --iov_len;
++ last_len = iov[iov_len - 1].iov_len - (4 - last_len);
++ }
++ else {
++ last_len = iov[iov_len - 1].iov_len - 4;
++ }
++ if( iov_len == 1 )
++ len = last_len;
++ }
++
++ while( 1 ) {
++ if( qs->added - qs->removed >= q->mask ) {
++ qs->added = added_save;
++ return -EAGAIN;
++ }
++
++ dma_len = (~((unsigned) dma_addr) & 0xfff) + 1;
++ if( dma_len > len ) dma_len = len;
++ { /* BUG5391_WORKAROUND */
++ unsigned misalign =
++ (unsigned) dma_addr & q->misalign_mask;
++ if( misalign && dma_len + misalign > 512 )
++ dma_len = 512 - misalign;
++ }
++
++ di = qs->added++ & q->mask;
++ dp = (ef_vi_falcon_dma_tx_buf_desc*) q->descriptors + di;
++ if( vi->vi_flags & EF_VI_TX_PHYS_ADDR )
++ falcon_dma_tx_calc_ip_phys
++ (ef_physaddr(dma_addr), dma_len, /*port*/ 0,
++ (iov_len == 1 && dma_len == len) ? 0 :
++ EFVI_FALCON_DMA_TX_FRAG, dp);
++ else
++ falcon_dma_tx_calc_ip_buf
++ (ef_bufaddr(dma_addr), dma_len, /*port*/ 0,
++ (iov_len == 1 && dma_len == len) ? 0 :
++ EFVI_FALCON_DMA_TX_FRAG, dp);
++
++ dma_addr += dma_len;
++ len -= dma_len;
++
++ if( len == 0 ) {
++ if( --iov_len == 0 ) break;
++ ++iov;
++ dma_addr = iov->iov_base;
++ len = iov->iov_len;
++ if( (vi->vi_flags & EF_VI_ISCSI_TX_DDIG) &&
++ (iov_len == 1) )
++ len = last_len;
++ }
++ }
++
++ q->ids[di] = (uint16_t) dma_id;
++ return 0;
++}
++
++
++void ef_vi_transmit_push(ef_vi* vi)
++{
++ ef_vi_wiob();
++ writel((vi->ep_state->txq.added & vi->vi_txq.mask) <<
++ __DW4(TX_DESC_WPTR_LBN),
++ vi->vi_txq.doorbell);
++}
++
++
++/*! The value of initial_rx_bytes is used to set RX_KER_BUF_SIZE in an initial
++** receive descriptor here if physical addressing is being used. A value of
++** zero represents 16384 bytes. This is okay, because caller must provide a
++** buffer than is > MTU, and mac should filter anything bigger than that.
++*/
++int ef_vi_receive_init(ef_vi* vi, ef_addr addr, ef_request_id dma_id,
++ int initial_rx_bytes)
++{
++ ef_vi_rxq* q = &vi->vi_rxq;
++ ef_vi_rxq_state* qs = &vi->ep_state->rxq;
++ unsigned di;
++
++ if( ef_vi_receive_space(vi) ) {
++ di = qs->added++ & q->mask;
++ ef_assert_equal(q->ids[di], 0xffff);
++ q->ids[di] = (uint16_t) dma_id;
++
++ if( ! (vi->vi_flags & EF_VI_RX_PHYS_ADDR) ) {
++ ef_vi_falcon_dma_rx_buf_desc* dp;
++ dp = (ef_vi_falcon_dma_rx_buf_desc*)
++ q->descriptors + di;
++ falcon_dma_rx_calc_ip_buf(ef_bufaddr(addr), dp);
++ }
++ else {
++ ef_vi_falcon_dma_rx_phys_desc* dp;
++ dp = (ef_vi_falcon_dma_rx_phys_desc*)
++ q->descriptors + di;
++ __falcon_dma_rx_calc_ip_phys(addr, dp,
++ initial_rx_bytes);
++ }
++
++ return 0;
++ }
++
++ return -EAGAIN;
++}
++
++
++void ef_vi_receive_push(ef_vi* vi)
++{
++ ef_vi_wiob();
++ writel ((vi->ep_state->rxq.added & vi->vi_rxq.mask) <<
++ __DW4(RX_DESC_WPTR_LBN),
++ vi->vi_rxq.doorbell);
++}
++
++
++ef_request_id ef_vi_receive_done(const ef_vi* vi, const ef_event* ef_ev)
++{
++ const ef_vi_qword* ev = EF_GET_HW_EV_PTR(*ef_ev);
++ unsigned di = ev->u32[0] & vi->vi_rxq.mask;
++ ef_request_id rq_id;
++
++ ef_assert(EF_EVENT_TYPE(*ef_ev) == EF_EVENT_TYPE_RX ||
++ EF_EVENT_TYPE(*ef_ev) == EF_EVENT_TYPE_RX_DISCARD);
++
++ /* Detect spurious / duplicate RX events. We may need to modify this
++ ** code so that we are robust if they happen. */
++ ef_assert_equal(di, vi->ep_state->rxq.removed & vi->vi_rxq.mask);
++
++ /* We only support 1 port: so events should be in order. */
++ ef_assert(vi->vi_rxq.ids[di] != 0xffff);
++
++ rq_id = vi->vi_rxq.ids[di];
++ vi->vi_rxq.ids[di] = 0xffff;
++ ++vi->ep_state->rxq.removed;
++ return rq_id;
++}
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/Makefile
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,11 @@
++EXTRA_CFLAGS += -Idrivers/xen/sfc_netfront -Idrivers/xen/sfc_netutil -Idrivers/xen/netfront
++EXTRA_CFLAGS += -D__ci_driver__
++EXTRA_CFLAGS += -Werror
++
++ifdef GCOV
++EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage -DEFX_GCOV
++endif
++
++obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND) := sfc_netfront.o
++
++sfc_netfront-objs := accel_msg.o accel_bufs.o accel_netfront.o accel_vi.o accel_xenbus.o accel_tso.o accel_ssr.o accel_debugfs.o falcon_event.o falcon_vi.o pt_tx.o vi_init.o
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/pt_tx.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/pt_tx.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/pt_tx.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/pt_tx.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,91 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr
++ * \brief Packet-mode transmit interface.
++ * \date 2003/04/02
++ */
++
++/*! \cidoxg_lib_ef */
++#include "ef_vi_internal.h"
++
++
++int ef_vi_transmit_init(ef_vi* vi, ef_addr base, int len, ef_request_id dma_id)
++{
++ ef_iovec iov = { base, len };
++ return ef_vi_transmitv_init(vi, &iov, 1, dma_id);
++}
++
++
++int ef_vi_transmit(ef_vi* vi, ef_addr base, int len, ef_request_id dma_id)
++{
++ ef_iovec iov = { base, len };
++ int rc = ef_vi_transmitv_init(vi, &iov, 1, dma_id);
++ if( rc == 0 ) ef_vi_transmit_push(vi);
++ return rc;
++}
++
++
++int ef_vi_transmitv(ef_vi* vi, const ef_iovec* iov, int iov_len,
++ ef_request_id dma_id)
++{
++ int rc = ef_vi_transmitv_init(vi, iov, iov_len, dma_id);
++ if( rc == 0 ) ef_vi_transmit_push(vi);
++ return rc;
++}
++
++
++int ef_vi_transmit_unbundle(ef_vi* vi, const ef_event* __ev,
++ ef_request_id* ids)
++{
++ ef_request_id* ids_in = ids;
++ ef_vi_txq* q = &vi->vi_txq;
++ ef_vi_txq_state* qs = &vi->ep_state->txq;
++ const ef_vi_qword* ev = EF_GET_HW_EV_PTR(*__ev);
++ unsigned i, stop = (ev->u32[0] + 1) & q->mask;
++
++ ef_assert(EF_EVENT_TYPE(*__ev) == EF_EVENT_TYPE_TX ||
++ EF_EVENT_TYPE(*__ev) == EF_EVENT_TYPE_TX_ERROR);
++
++ /* Shouldn't be batching more than 64 descriptors, and should not go
++ ** backwards. */
++ ef_assert_le((((ev->u32[0] + 1) - qs->removed) & q->mask), 64);
++ /* Should not complete more than we've posted. */
++ ef_assert_le((((ev->u32[0] + 1) - qs->removed) & q->mask),
++ qs->added - qs->removed);
++
++ for( i = qs->removed & q->mask; i != stop; i = ++qs->removed & q->mask )
++ if( q->ids[i] != 0xffff ) {
++ *ids++ = q->ids[i];
++ q->ids[i] = 0xffff;
++ }
++
++ ef_assert_le(ids - ids_in, EF_VI_TRANSMIT_BATCH);
++
++ return (int) (ids - ids_in);
++}
++
++/*! \cidoxg_end */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/sysdep.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/sysdep.h
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/sysdep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/sysdep.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,184 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author stg
++ * \brief System dependent support for ef vi lib
++ * \date 2007/05/10
++ */
++
++/*! \cidoxg_include_ci_ul */
++#ifndef __CI_CIUL_SYSDEP_LINUX_H__
++#define __CI_CIUL_SYSDEP_LINUX_H__
++
++/**********************************************************************
++ * Kernel version compatability
++ */
++
++#if defined(__GNUC__)
++
++/* Linux kernel doesn't have stdint.h or [u]intptr_t. */
++# if !defined(LINUX_VERSION_CODE)
++# include <linux/version.h>
++# endif
++# include <asm/io.h>
++
++/* In Linux 2.6.24, linux/types.h has uintptr_t */
++# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
++# if BITS_PER_LONG == 32
++ typedef __u32 uintptr_t;
++# else
++ typedef __u64 uintptr_t;
++# endif
++# endif
++
++/* But even 2.6.24 doesn't define intptr_t */
++# if BITS_PER_LONG == 32
++ typedef __s32 intptr_t;
++# else
++ typedef __s64 intptr_t;
++# endif
++
++# if defined(__ia64__)
++# define EF_VI_PRIx64 "lx"
++# else
++# define EF_VI_PRIx64 "llx"
++# endif
++
++# define EF_VI_HF __attribute__((visibility("hidden")))
++# define EF_VI_HV __attribute__((visibility("hidden")))
++
++# if defined(__i386__) || defined(__x86_64__) /* GCC x86/x64 */
++ typedef unsigned long long ef_vi_dma_addr_t;
++# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
++# define ef_vi_wiob() __asm__ __volatile__ ("sfence")
++# else
++# define ef_vi_wiob() __asm__ __volatile__ (".byte 0x0F, 0xAE, 0xF8")
++# endif
++
++# endif
++#endif
++
++#ifdef EFX_NOT_UPSTREAM
++
++/* Stuff for architectures/compilers not officially supported */
++
++#if !defined(__GNUC__)
++# if defined(__PPC__) /* GCC, PPC */
++ typedef unsigned long ef_vi_dma_addr_t;
++# define ef_vi_wiob() wmb()
++
++# ifdef __powerpc64__
++# ifdef CONFIG_SMP
++# define CI_SMP_SYNC "\n eieio \n" /* memory cache sync */
++# define CI_SMP_ISYNC "\n isync \n" /* instr cache sync */
++# else
++# define CI_SMP_SYNC
++# define CI_SMP_ISYNC
++# endif
++# else /* for ppc32 systems */
++# ifdef CONFIG_SMP
++# define CI_SMP_SYNC "\n eieio \n"
++# define CI_SMP_ISYNC "\n sync \n"
++# else
++# define CI_SMP_SYNC
++# define CI_SMP_ISYNC
++# endif
++# endif
++
++# elif defined(__ia64__) /* GCC, IA64 */
++ typedef unsigned long ef_vi_dma_addr_t;
++# define ef_vi_wiob() __asm__ __volatile__("mf.a": : :"memory")
++
++# else
++# error Unknown processor - GNU C
++# endif
++
++#elif defined(__PGI)
++# error PGI not supported
++
++#elif defined(__INTEL_COMPILER)
++
++/* Intel compilers v7 claim to be very gcc compatible. */
++# if __INTEL_COMPILER >= 700
++# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ > 91)
++# define EF_VI_LIKELY(t) __builtin_expect((t), 1)
++# define EF_VI_UNLIKELY(t) __builtin_expect((t), 0)
++# endif
++
++# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
++# define ef_vi_wiob() __asm__ __volatile__ ("sfence")
++# else
++# define ef_vi_wiob() __asm__ __volatile__ (".byte 0x0F, 0xAE, 0xF8")
++# endif
++
++# else
++# error Old Intel compiler not supported.
++# endif
++
++#else
++# error Unknown compiler.
++#endif
++
++#endif
++
++
++# include <linux/errno.h>
++
++
++/**********************************************************************
++ * Extracting bit fields.
++ */
++
++#define _QWORD_GET_LOW(f, v) \
++ (((v).u32[0] >> (f##_LBN)) & ((1u << f##_WIDTH) - 1u))
++#define _QWORD_GET_HIGH(f, v) \
++ (((v).u32[1] >> (f##_LBN - 32u)) & ((1u << f##_WIDTH) - 1u))
++#define _QWORD_GET_ANY(f, v) \
++ (((v).u64[0] >> f##_LBN) & (((uint64_t) 1u << f##_WIDTH) - 1u))
++
++#define QWORD_GET(f, v) \
++ ((f##_LBN + f##_WIDTH) <= 32u \
++ ? _QWORD_GET_LOW(f, (v)) \
++ : ((f##_LBN >= 32u) ? _QWORD_GET_HIGH(f, (v)) : _QWORD_GET_ANY(f, (v))))
++
++#define QWORD_GET_U(f, v) ((unsigned) QWORD_GET(f, (v)))
++
++#define _QWORD_TEST_BIT_LOW(f, v) ((v).u32[0] & (1u << (f##_LBN)))
++#define _QWORD_TEST_BIT_HIGH(f, v) ((v).u32[1] & (1u << (f##_LBN - 32u)))
++
++#define QWORD_TEST_BIT(f, v) \
++ (f##_LBN < 32 ? _QWORD_TEST_BIT_LOW(f, (v)) : _QWORD_TEST_BIT_HIGH(f, (v)))
++
++
++
++
++#ifndef DECLSPEC_NORETURN
++/* normally defined on Windows to expand to a declaration that the
++ function will not return */
++# define DECLSPEC_NORETURN
++#endif
++
++#endif /* __CI_CIUL_SYSDEP_LINUX_H__ */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netfront/vi_init.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/vi_init.c
+--- linux-2.6.18.8/drivers/xen/sfc_netfront/vi_init.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netfront/vi_init.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,183 @@
++/****************************************************************************
++ * Copyright 2002-2005: Level 5 Networks Inc.
++ * Copyright 2005-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications
++ * <linux-xen-drivers@solarflare.com>
++ * <onload-dev@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * \author djr
++ * \brief Initialisation of VIs.
++ * \date 2007/06/08
++ */
++
++#include "ef_vi_internal.h"
++
++#define EF_VI_STATE_BYTES(rxq_sz, txq_sz) \
++ (sizeof(ef_vi_state) + (rxq_sz) * sizeof(uint16_t) \
++ + (txq_sz) * sizeof(uint16_t))
++
++int ef_vi_calc_state_bytes(int rxq_sz, int txq_sz)
++{
++ ef_assert(rxq_sz == 0 || EF_VI_IS_POW2(rxq_sz));
++ ef_assert(txq_sz == 0 || EF_VI_IS_POW2(txq_sz));
++
++ return EF_VI_STATE_BYTES(rxq_sz, txq_sz);
++}
++
++
++int ef_vi_state_bytes(ef_vi* vi)
++{
++ int rxq_sz = 0, txq_sz = 0;
++ if( ef_vi_receive_capacity(vi) )
++ rxq_sz = ef_vi_receive_capacity(vi) + 1;
++ if( ef_vi_transmit_capacity(vi) )
++ txq_sz = ef_vi_transmit_capacity(vi) + 1;
++
++ ef_assert(rxq_sz == 0 || EF_VI_IS_POW2(rxq_sz));
++ ef_assert(txq_sz == 0 || EF_VI_IS_POW2(txq_sz));
++
++ return EF_VI_STATE_BYTES(rxq_sz, txq_sz);
++}
++
++
++void ef_eventq_state_init(ef_vi* evq)
++{
++ int j;
++
++ for (j = 0; j<EFAB_DMAQS_PER_EVQ_MAX; j++) {
++ ef_rx_dup_state_t *rx_dup_state =
++ &evq->evq_state->rx_dup_state[j];
++ rx_dup_state->bad_sop = 0;
++ rx_dup_state->rx_last_desc_ptr = -1;
++ rx_dup_state->frag_num = 0;
++ }
++
++ evq->evq_state->evq_ptr = 0;
++}
++
++
++void ef_vi_state_init(ef_vi* vi)
++{
++ ef_vi_state* state = vi->ep_state;
++ unsigned i;
++
++ state->txq.added = state->txq.removed = 0;
++ state->rxq.added = state->rxq.removed = 0;
++
++ if( vi->vi_rxq.mask )
++ for( i = 0; i <= vi->vi_rxq.mask; ++i )
++ vi->vi_rxq.ids[i] = (uint16_t) -1;
++ if( vi->vi_txq.mask )
++ for( i = 0; i <= vi->vi_txq.mask; ++i )
++ vi->vi_txq.ids[i] = (uint16_t) -1;
++}
++
++
++void ef_vi_init_mapping_evq(void* data_area, struct ef_vi_nic_type nic_type,
++ int instance, unsigned evq_bytes, void* base,
++ void* timer_reg)
++{
++ struct vi_mappings* vm = (struct vi_mappings*) data_area;
++
++ vm->signature = VI_MAPPING_SIGNATURE;
++ vm->vi_instance = instance;
++ vm->nic_type = nic_type;
++ vm->evq_bytes = evq_bytes;
++ vm->evq_base = base;
++ vm->evq_timer_reg = timer_reg;
++}
++
++
++void ef_vi_init(ef_vi* vi, void* vvis, ef_vi_state* state,
++ ef_eventq_state* evq_state, enum ef_vi_flags vi_flags)
++{
++ struct vi_mappings* vm = (struct vi_mappings*) vvis;
++
++ vi->vi_i = vm->vi_instance;
++ vi->ep_state = state;
++ vi->vi_flags = vi_flags;
++
++ switch( vm->nic_type.arch ) {
++ case EF_VI_ARCH_FALCON:
++ falcon_vi_init(vi, vvis);
++ break;
++ default:
++ /* ?? TODO: We should return an error code. */
++ ef_assert(0);
++ break;
++ }
++
++ if( vm->evq_bytes ) {
++ vi->evq_state = evq_state;
++ vi->evq_mask = vm->evq_bytes - 1u;
++ vi->evq_base = vm->evq_base;
++ vi->evq_timer_reg = vm->evq_timer_reg;
++ }
++
++ EF_VI_MAGIC_SET(vi, EF_VI);
++}
++
++
++/* Initialise [data_area] with information required to initialise an ef_vi.
++ * In the following, an unused param should be set to NULL. Note the case
++ * marked (*) of [iobuf_mmap] for falcon/driver; for the normal driver this
++ * must be NULL.
++ *
++ * \param data_area [in,out] required, must ref at least VI_MAPPING_SIZE
++ * bytes
++ * \param io_mmap [in] ef1, required
++ * falcon, required
++ * \param iobuf_mmap [in] ef1, unused
++ * falcon, required
++ */
++void ef_vi_init_mapping_vi(void* data_area, struct ef_vi_nic_type nic_type,
++ unsigned rxq_capacity, unsigned txq_capacity,
++ int instance, void* io_mmap,
++ void* iobuf_mmap_rx, void* iobuf_mmap_tx,
++ enum ef_vi_flags vi_flags)
++{
++ struct vi_mappings* vm = (struct vi_mappings*) data_area;
++ int rx_desc_bytes, rxq_bytes;
++
++ ef_assert(rxq_capacity > 0 || txq_capacity > 0);
++ ef_assert(vm);
++ ef_assert(io_mmap);
++ ef_assert(iobuf_mmap_rx || iobuf_mmap_tx);
++
++ vm->signature = VI_MAPPING_SIGNATURE;
++ vm->vi_instance = instance;
++ vm->nic_type = nic_type;
++
++ rx_desc_bytes = (vi_flags & EF_VI_RX_PHYS_ADDR) ? 8 : 4;
++ rxq_bytes = rxq_capacity * rx_desc_bytes;
++ rxq_bytes = (rxq_bytes + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
++
++ if( iobuf_mmap_rx == iobuf_mmap_tx )
++ iobuf_mmap_tx = (char*) iobuf_mmap_rx + rxq_bytes;
++
++ vm->rx_queue_capacity = rxq_capacity;
++ vm->rx_dma_falcon = iobuf_mmap_rx;
++ vm->rx_bell = (char*) io_mmap + (RX_DESC_UPD_REG_KER_OFST & 4095);
++ vm->tx_queue_capacity = txq_capacity;
++ vm->tx_dma_falcon = iobuf_mmap_tx;
++ vm->tx_bell = (char*) io_mmap + (TX_DESC_UPD_REG_KER_OFST & 4095);
++}
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netutil/accel_cuckoo_hash.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_cuckoo_hash.c
+--- linux-2.6.18.8/drivers/xen/sfc_netutil/accel_cuckoo_hash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_cuckoo_hash.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,651 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/types.h> /* needed for linux/random.h */
++#include <linux/random.h>
++
++#include "accel_cuckoo_hash.h"
++#include "accel_util.h"
++
++static inline int cuckoo_hash_key_compare(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key1,
++ cuckoo_hash_key *key2)
++{
++ return !memcmp(key1, key2, hashtab->key_length);
++}
++
++
++static inline void cuckoo_hash_key_set(cuckoo_hash_key *key1,
++ cuckoo_hash_key *key2)
++{
++ *key1 = *key2;
++}
++
++
++/*
++ * Sets hash function parameters. Chooses "a" to be odd, 0 < a < 2^w
++ * where w is the length of the key
++ */
++static void set_hash_parameters(cuckoo_hash_table *hashtab)
++{
++ again:
++ hashtab->a0 = hashtab->a1 = 0;
++
++ /* Make sure random */
++ get_random_bytes(&hashtab->a0, hashtab->key_length);
++ get_random_bytes(&hashtab->a1, hashtab->key_length);
++
++ /* Make sure odd */
++ hashtab->a0 |= 1;
++ hashtab->a1 |= 1;
++
++ /* Being different is good */
++ if (hashtab->a0 != hashtab->a1)
++ return;
++
++ goto again;
++}
++
++int cuckoo_hash_init(cuckoo_hash_table *hashtab, unsigned length_bits,
++ unsigned key_length)
++{
++ char *table_mem;
++ unsigned length = 1 << length_bits;
++
++ BUG_ON(length_bits >= sizeof(unsigned) * 8);
++ BUG_ON(key_length > sizeof(cuckoo_hash_key));
++
++ table_mem = kmalloc(sizeof(cuckoo_hash_entry) * 2 * length, GFP_KERNEL);
++
++ if (table_mem == NULL)
++ return -ENOMEM;
++
++ hashtab->length = length;
++ hashtab->length_bits = length_bits;
++ hashtab->key_length = key_length;
++ hashtab->entries = 0;
++
++ hashtab->table0 = (cuckoo_hash_entry *)table_mem;
++ hashtab->table1 = (cuckoo_hash_entry *)
++ (table_mem + length * sizeof(cuckoo_hash_entry));
++
++ set_hash_parameters(hashtab);
++
++ /* Zero the table */
++ memset(hashtab->table0, 0, length * 2 * sizeof(cuckoo_hash_entry));
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_init);
++
++void cuckoo_hash_destroy(cuckoo_hash_table *hashtab)
++{
++ if (hashtab->table0 != NULL)
++ kfree(hashtab->table0);
++}
++
++EXPORT_SYMBOL_GPL(cuckoo_hash_destroy);
++
++/*
++ * This computes sizeof(cuckoo_hash) bits of hash, not all will be
++ * necessarily used, but the hash function throws away any that
++ * aren't
++ */
++static inline void cuckoo_compute_hash_helper(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *a,
++ cuckoo_hash_key *x,
++ cuckoo_hash *result)
++{
++ u64 multiply_result = 0, a_temp, x_temp;
++ u32 carry = 0;
++ u32 *a_words;
++ u32 *x_words;
++ int i;
++
++ /*
++ * As the mod and div operations in the function effectively
++ * reduce and shift the bits of the product down to just the
++ * third word, we need only compute that and return it as a
++ * result.
++ *
++ * Do enough long multiplication to get the word we need
++ */
++
++ /* This assumes things about the sizes of the key and hash */
++ BUG_ON(hashtab->key_length % sizeof(u32) != 0);
++ BUG_ON(sizeof(cuckoo_hash) != sizeof(u32));
++
++ a_words = (u32 *)a;
++ x_words = (u32 *)x;
++
++ for (i = 0; i < hashtab->key_length / sizeof(u32); i++) {
++ a_temp = a_words[i];
++ x_temp = x_words[i];
++
++ multiply_result = (a_temp * x_temp) + carry;
++ carry = (multiply_result >> 32) & 0xffffffff;
++ }
++
++ *result = multiply_result & 0xffffffff;
++}
++
++
++/*
++ * Want to implement (ax mod 2^w) div 2^(w-q) for odd a, 0 < a < 2^w;
++ * w is the length of the key, q is the length of the hash, I think.
++ * See http://www.it-c.dk/people/pagh/papers/cuckoo-jour.pdf
++ */
++static cuckoo_hash cuckoo_compute_hash(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key,
++ cuckoo_hash_key *a)
++{
++ unsigned q = hashtab->length_bits;
++ unsigned shift = 32 - q;
++ unsigned mask = ((1 << q) - 1) << shift;
++ cuckoo_hash hash;
++
++ cuckoo_compute_hash_helper(hashtab, a, key, &hash);
++
++ /*
++ * Take the top few bits to get the right length for this
++ * hash table
++ */
++ hash = (hash & mask) >> shift;
++
++ BUG_ON(hash >= hashtab->length);
++
++ return hash;
++}
++
++
++static int cuckoo_hash_lookup0(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key,
++ cuckoo_hash_value *value)
++{
++ cuckoo_hash hash = cuckoo_compute_hash(hashtab, key, &hashtab->a0);
++
++ if ((hashtab->table0[hash].state == CUCKOO_HASH_STATE_OCCUPIED)
++ && cuckoo_hash_key_compare(hashtab, &(hashtab->table0[hash].key),
++ key)) {
++ *value = hashtab->table0[hash].value;
++ return 1;
++ }
++
++ return 0;
++}
++
++static int cuckoo_hash_lookup1(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key,
++ cuckoo_hash_value *value)
++{
++ cuckoo_hash hash = cuckoo_compute_hash(hashtab, key, &hashtab->a1);
++
++ if ((hashtab->table1[hash].state == CUCKOO_HASH_STATE_OCCUPIED)
++ && cuckoo_hash_key_compare(hashtab, &(hashtab->table1[hash].key),
++ key)) {
++ *value = hashtab->table1[hash].value;
++ return 1;
++ }
++
++ return 0;
++}
++
++
++int cuckoo_hash_lookup(cuckoo_hash_table *hashtab, cuckoo_hash_key *key,
++ cuckoo_hash_value *value)
++{
++ return cuckoo_hash_lookup0(hashtab, key, value)
++ || cuckoo_hash_lookup1(hashtab, key, value);
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_lookup);
++
++
++/* Transfer any active entries from "old_table" into hashtab */
++static int cuckoo_hash_transfer_entries(cuckoo_hash_table *hashtab,
++ cuckoo_hash_entry *old_table,
++ unsigned capacity)
++{
++ int i, rc;
++ cuckoo_hash_entry *entry;
++
++ hashtab->entries = 0;
++
++ for (i = 0; i < capacity; i++) {
++ entry = &old_table[i];
++ if (entry->state == CUCKOO_HASH_STATE_OCCUPIED) {
++ rc = cuckoo_hash_add(hashtab, &(entry->key),
++ entry->value, 0);
++ if (rc != 0) {
++ return rc;
++ }
++ }
++ }
++
++ return 0;
++}
++
++
++int cuckoo_hash_rehash(cuckoo_hash_table *hashtab)
++{
++ cuckoo_hash_entry *new_table;
++ cuckoo_hash_table old_hashtab;
++ int resize = 0, rc, rehash_count;
++
++ /*
++ * Store old tables so we can access the existing values and
++ * copy across
++ */
++ memcpy(&old_hashtab, hashtab, sizeof(cuckoo_hash_table));
++
++ /* resize if hashtable is more than half full */
++ if (old_hashtab.entries > old_hashtab.length &&
++ old_hashtab.length_bits < 32)
++ resize = 1;
++
++ resize:
++ if (resize) {
++ new_table = kmalloc(sizeof(cuckoo_hash_entry) * 4 * hashtab->length,
++ GFP_ATOMIC);
++ if (new_table == NULL) {
++ rc = -ENOMEM;
++ goto err;
++ }
++
++ hashtab->length = 2 * hashtab->length;
++ hashtab->length_bits++;
++ } else {
++ new_table = kmalloc(sizeof(cuckoo_hash_entry) * 2 * hashtab->length,
++ GFP_ATOMIC);
++ if (new_table == NULL) {
++ rc = -ENOMEM;
++ goto err;
++ }
++ }
++
++ /*
++ * Point hashtab to new memory region so we can try to
++ * construct new table
++ */
++ hashtab->table0 = new_table;
++ hashtab->table1 = (cuckoo_hash_entry *)
++ ((char *)new_table + hashtab->length * sizeof(cuckoo_hash_entry));
++
++ rehash_count = 0;
++
++ again:
++ /* Zero the new tables */
++ memset(new_table, 0, hashtab->length * 2 * sizeof(cuckoo_hash_entry));
++
++ /* Choose new parameters for the hash functions */
++ set_hash_parameters(hashtab);
++
++ /*
++ * Multiply old_table_length by 2 as the length refers to each
++ * table, and there are two of them. This assumes that they
++ * are arranged sequentially in memory, so assert it
++ */
++ BUG_ON(((char *)old_hashtab.table1) !=
++ ((char *)old_hashtab.table0 + old_hashtab.length
++ * sizeof(cuckoo_hash_entry)));
++ rc = cuckoo_hash_transfer_entries(hashtab, old_hashtab.table0,
++ old_hashtab.length * 2);
++ if (rc < 0) {
++ /* Problem */
++ if (rc == -ENOSPC) {
++ ++rehash_count;
++ if (rehash_count < CUCKOO_HASH_MAX_LOOP) {
++ /*
++ * Wanted to rehash, but rather than
++ * recurse we can just do it here
++ */
++ goto again;
++ } else {
++ /*
++ * Didn't manage to rehash, so let's
++ * go up a size (if we haven't already
++ * and there's space)
++ */
++ if (!resize && hashtab->length_bits < 32) {
++ resize = 1;
++ kfree(new_table);
++ goto resize;
++ }
++ else
++ goto err;
++ }
++ }
++ else
++ goto err;
++ }
++
++ /* Success, I think. Free up the old table */
++ kfree(old_hashtab.table0);
++
++ /* We should have put all the entries from old table in the new one */
++ BUG_ON(hashtab->entries != old_hashtab.entries);
++
++ return 0;
++ err:
++ EPRINTK("%s: Rehash failed, giving up\n", __FUNCTION__);
++ /* Some other error, give up, at least restore table to how it was */
++ memcpy(hashtab, &old_hashtab, sizeof(cuckoo_hash_table));
++ if (new_table)
++ kfree(new_table);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_rehash);
++
++
++static int
++cuckoo_hash_insert_or_displace(cuckoo_hash_entry *table, unsigned hash,
++ cuckoo_hash_key *key,
++ cuckoo_hash_value value,
++ cuckoo_hash_key *displaced_key,
++ cuckoo_hash_value *displaced_value)
++{
++ if (table[hash].state == CUCKOO_HASH_STATE_VACANT) {
++ cuckoo_hash_key_set(&(table[hash].key), key);
++ table[hash].value = value;
++ table[hash].state = CUCKOO_HASH_STATE_OCCUPIED;
++
++ return 1;
++ } else {
++ cuckoo_hash_key_set(displaced_key, &(table[hash].key));
++ *displaced_value = table[hash].value;
++ cuckoo_hash_key_set(&(table[hash].key), key);
++ table[hash].value = value;
++
++ return 0;
++ }
++}
++
++
++int cuckoo_hash_add(cuckoo_hash_table *hashtab, cuckoo_hash_key *key,
++ cuckoo_hash_value value, int can_rehash)
++{
++ cuckoo_hash hash0, hash1;
++ int i, rc;
++ cuckoo_hash_key key1, key2;
++
++ cuckoo_hash_key_set(&key1, key);
++
++ again:
++ i = 0;
++ do {
++ hash0 = cuckoo_compute_hash(hashtab, &key1, &hashtab->a0);
++ if (cuckoo_hash_insert_or_displace(hashtab->table0, hash0,
++ &key1, value, &key2,
++ &value)) {
++ /* Success */
++ hashtab->entries++;
++ return 0;
++ }
++
++ hash1 = cuckoo_compute_hash(hashtab, &key2, &hashtab->a1);
++ if (cuckoo_hash_insert_or_displace(hashtab->table1, hash1,
++ &key2, value, &key1,
++ &value)) {
++ /* Success */
++ hashtab->entries++;
++ return 0;
++ }
++ } while (++i < CUCKOO_HASH_MAX_LOOP);
++
++ if (can_rehash) {
++ if ((rc = cuckoo_hash_rehash(hashtab)) < 0) {
++ /*
++ * Give up - this will drop whichever
++ * key/value pair we have currently displaced
++ * on the floor
++ */
++ return rc;
++ }
++ goto again;
++ }
++
++ EPRINTK("%s: failed hash add\n", __FUNCTION__);
++ /*
++ * Couldn't do it - bad as we've now removed some random thing
++ * from the table, and will just drop it on the floor. Better
++ * would be to somehow revert the table to the state it was in
++ * at the start
++ */
++ return -ENOSPC;
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_add);
++
++
++int cuckoo_hash_add_check(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key, cuckoo_hash_value value,
++ int can_rehash)
++{
++ int stored_value;
++
++ if (cuckoo_hash_lookup(hashtab, key, &stored_value))
++ return -EBUSY;
++
++ return cuckoo_hash_add(hashtab, key, value, can_rehash);
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_add_check);
++
++
++int cuckoo_hash_remove(cuckoo_hash_table *hashtab, cuckoo_hash_key *key)
++{
++ cuckoo_hash hash;
++
++ hash = cuckoo_compute_hash(hashtab, key, &hashtab->a0);
++ if ((hashtab->table0[hash].state == CUCKOO_HASH_STATE_OCCUPIED) &&
++ cuckoo_hash_key_compare(hashtab, &(hashtab->table0[hash].key),
++ key)) {
++ hashtab->table0[hash].state = CUCKOO_HASH_STATE_VACANT;
++ hashtab->entries--;
++ return 0;
++ }
++
++ hash = cuckoo_compute_hash(hashtab, key, &hashtab->a1);
++ if ((hashtab->table1[hash].state == CUCKOO_HASH_STATE_OCCUPIED) &&
++ cuckoo_hash_key_compare(hashtab, &(hashtab->table1[hash].key),
++ key)) {
++ hashtab->table1[hash].state = CUCKOO_HASH_STATE_VACANT;
++ hashtab->entries--;
++ return 0;
++ }
++
++ return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_remove);
++
++
++int cuckoo_hash_update(cuckoo_hash_table *hashtab, cuckoo_hash_key *key,
++ cuckoo_hash_value value)
++{
++ cuckoo_hash hash;
++
++ hash = cuckoo_compute_hash(hashtab, key, &hashtab->a0);
++ if ((hashtab->table0[hash].state == CUCKOO_HASH_STATE_OCCUPIED) &&
++ cuckoo_hash_key_compare(hashtab, &(hashtab->table0[hash].key),
++ key)) {
++ hashtab->table0[hash].value = value;
++ return 0;
++ }
++
++ hash = cuckoo_compute_hash(hashtab, key, &hashtab->a1);
++ if ((hashtab->table1[hash].state == CUCKOO_HASH_STATE_OCCUPIED) &&
++ cuckoo_hash_key_compare(hashtab, &(hashtab->table1[hash].key),
++ key)) {
++ hashtab->table1[hash].value = value;
++ return 0;
++ }
++
++ return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_update);
++
++
++void cuckoo_hash_iterate_reset(cuckoo_hash_table *hashtab)
++{
++ hashtab->iterate_index = 0;
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_iterate_reset);
++
++
++int cuckoo_hash_iterate(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key, cuckoo_hash_value *value)
++{
++ unsigned index;
++
++ while (hashtab->iterate_index < hashtab->length) {
++ index = hashtab->iterate_index;
++ ++hashtab->iterate_index;
++ if (hashtab->table0[index].state == CUCKOO_HASH_STATE_OCCUPIED) {
++ *key = hashtab->table0[index].key;
++ *value = hashtab->table0[index].value;
++ return 0;
++ }
++ }
++
++ while (hashtab->iterate_index >= hashtab->length &&
++ hashtab->iterate_index < hashtab->length * 2) {
++ index = hashtab->iterate_index - hashtab->length;
++ ++hashtab->iterate_index;
++ if (hashtab->table1[index].state == CUCKOO_HASH_STATE_OCCUPIED) {
++ *key = hashtab->table1[index].key;
++ *value = hashtab->table1[index].value;
++ return 0;
++ }
++ }
++
++ return -ENOSPC;
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_iterate);
++
++
++#if 0
++void cuckoo_hash_valid(cuckoo_hash_table *hashtab)
++{
++ int i, entry_count = 0;
++
++ for (i=0; i < hashtab->length; i++) {
++ EPRINTK_ON(hashtab->table0[i].state != CUCKOO_HASH_STATE_VACANT &&
++ hashtab->table0[i].state != CUCKOO_HASH_STATE_OCCUPIED);
++ if (hashtab->table0[i].state == CUCKOO_HASH_STATE_OCCUPIED)
++ entry_count++;
++ EPRINTK_ON(hashtab->table1[i].state != CUCKOO_HASH_STATE_VACANT &&
++ hashtab->table1[i].state != CUCKOO_HASH_STATE_OCCUPIED);
++ if (hashtab->table1[i].state == CUCKOO_HASH_STATE_OCCUPIED)
++ entry_count++;
++ }
++
++ if (entry_count != hashtab->entries) {
++ EPRINTK("%s: bad count\n", __FUNCTION__);
++ cuckoo_hash_dump(hashtab);
++ return;
++ }
++
++ for (i=0; i< hashtab->length; i++) {
++ if (hashtab->table0[i].state == CUCKOO_HASH_STATE_OCCUPIED)
++ if (i != cuckoo_compute_hash(hashtab,
++ &hashtab->table0[i].key,
++ &hashtab->a0)) {
++ EPRINTK("%s: Bad key table 0 index %d\n",
++ __FUNCTION__, i);
++ cuckoo_hash_dump(hashtab);
++ return;
++ }
++ if (hashtab->table1[i].state == CUCKOO_HASH_STATE_OCCUPIED)
++ if (i != cuckoo_compute_hash(hashtab,
++ &hashtab->table1[i].key,
++ &hashtab->a1)) {
++ EPRINTK("%s: Bad key table 1 index %d\n",
++ __FUNCTION__, i);
++ cuckoo_hash_dump(hashtab);
++ return;
++ }
++ }
++
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_valid);
++
++
++void cuckoo_hash_dump(cuckoo_hash_table *hashtab)
++{
++ int i, entry_count;
++
++ entry_count = 0;
++ for (i=0; i < hashtab->length; i++) {
++ EPRINTK_ON(hashtab->table0[i].state != CUCKOO_HASH_STATE_VACANT &&
++ hashtab->table0[i].state != CUCKOO_HASH_STATE_OCCUPIED);
++ if (hashtab->table0[i].state == CUCKOO_HASH_STATE_OCCUPIED)
++ entry_count++;
++ EPRINTK_ON(hashtab->table1[i].state != CUCKOO_HASH_STATE_VACANT &&
++ hashtab->table1[i].state != CUCKOO_HASH_STATE_OCCUPIED);
++ if (hashtab->table1[i].state == CUCKOO_HASH_STATE_OCCUPIED)
++ entry_count++;
++ }
++
++ EPRINTK("======================\n");
++ EPRINTK("Cuckoo hash table dump\n");
++ EPRINTK("======================\n");
++ EPRINTK("length: %d; length_bits: %d; key_length: %d\n", hashtab->length,
++ hashtab->length_bits, hashtab->key_length);
++ EPRINTK("Recorded entries: %d\n", hashtab->entries);
++ EPRINTK("Counted entries: %d\n", entry_count);
++ EPRINTK("a0: %llx; a1: %llx\n", hashtab->a0, hashtab->a1);
++ EPRINTK("-----------------------------------------\n");
++ EPRINTK("Index Occupied Key Value Index0 Index1\n");
++ EPRINTK("-----------------------------------------\n");
++ for (i=0; i< hashtab->length; i++) {
++ if (hashtab->table0[i].state == CUCKOO_HASH_STATE_OCCUPIED)
++ EPRINTK("%d %d %llx %d %d %d\n", i,
++ hashtab->table0[i].state == CUCKOO_HASH_STATE_OCCUPIED,
++ hashtab->table0[i].key, hashtab->table0[i].value,
++ cuckoo_compute_hash(hashtab, &hashtab->table0[i].key,
++ &hashtab->a0),
++ cuckoo_compute_hash(hashtab, &hashtab->table0[i].key,
++ &hashtab->a1));
++ else
++ EPRINTK("%d %d - - - -\n", i,
++ hashtab->table0[i].state == CUCKOO_HASH_STATE_OCCUPIED);
++
++ }
++ EPRINTK("-----------------------------------------\n");
++ EPRINTK("Index Occupied Key Value Index0 Index1\n");
++ EPRINTK("-----------------------------------------\n");
++ for (i=0; i< hashtab->length; i++) {
++ if (hashtab->table1[i].state == CUCKOO_HASH_STATE_OCCUPIED)
++ EPRINTK("%d %d %llx %d %d %d\n", i,
++ hashtab->table1[i].state == CUCKOO_HASH_STATE_OCCUPIED,
++ hashtab->table1[i].key, hashtab->table1[i].value,
++ cuckoo_compute_hash(hashtab, &hashtab->table1[i].key,
++ &hashtab->a0),
++ cuckoo_compute_hash(hashtab, &hashtab->table1[i].key,
++ &hashtab->a1));
++ else
++ EPRINTK("%d %d - - - -\n", i,
++ hashtab->table1[i].state == CUCKOO_HASH_STATE_OCCUPIED);
++ }
++ EPRINTK("======================\n");
++}
++EXPORT_SYMBOL_GPL(cuckoo_hash_dump);
++#endif
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netutil/accel_cuckoo_hash.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_cuckoo_hash.h
+--- linux-2.6.18.8/drivers/xen/sfc_netutil/accel_cuckoo_hash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_cuckoo_hash.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,227 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++/*
++ * A cuckoo hash table consists of two sub tables. Each entry can
++ * hash to a position in each table. If, on entry, its position is
++ * found to be occupied, the existing element is moved to it's other
++ * location. This recurses until success or a loop is found. If a
++ * loop is found the table is rehashed.
++ *
++ * See http://www.it-c.dk/people/pagh/papers/cuckoo-jour.pdf
++ */
++
++#ifndef NET_ACCEL_CUCKOO_HASH_H
++#define NET_ACCEL_CUCKOO_HASH_H
++
++/*! Type used for hash table keys of ip pairs */
++typedef struct {
++ u32 local_ip;
++ //u32 remote_ip;
++ u16 local_port;
++ //u16 remote_port;
++ /* Technically only 1 bit, but use 16 to make key a round
++ number size */
++ u16 proto;
++} cuckoo_hash_ip_key;
++
++/*! Type used for hash table keys of mac addresses */
++typedef u64 cuckoo_hash_mac_key;
++
++/*! This type is designed to be large enough to hold all supported key
++ * sizes to avoid having to malloc storage for them.
++ */
++typedef u64 cuckoo_hash_key;
++
++/*! Type used for the values stored in the hash table */
++typedef int cuckoo_hash_value;
++
++/*! Type used for the hash used to index the table */
++typedef u32 cuckoo_hash;
++
++/*! How long to spend displacing values when adding before giving up
++ * and rehashing */
++#define CUCKOO_HASH_MAX_LOOP (hashtab->length)
++
++/*! State of hash table entry */
++typedef enum {
++ CUCKOO_HASH_STATE_VACANT = 0,
++ CUCKOO_HASH_STATE_OCCUPIED
++} cuckoo_hash_state;
++
++/*! An entry in the hash table */
++typedef struct {
++ cuckoo_hash_state state;
++ cuckoo_hash_key key;
++ cuckoo_hash_value value;
++} cuckoo_hash_entry;
++
++/*! A cuckoo hash table */
++typedef struct {
++ /*! The length of each table (NB. there are two tables of this
++ * length) */
++ unsigned length;
++ /*! The length of each table in bits */
++ unsigned length_bits;
++ /*! The length of the key in bytes */
++ unsigned key_length;
++ /*! The number of entries currently stored in the table */
++ unsigned entries;
++ /*! Index into table used by cuckoo_hash_iterate */
++ unsigned iterate_index;
++
++ /* parameter of hash functions */
++ /*! The "a" parameter of the first hash function */
++ cuckoo_hash_key a0;
++ /*! The "a" parameter of the second hash function */
++ cuckoo_hash_key a1;
++
++ /*! The first table */
++ cuckoo_hash_entry *table0;
++ /*! The second table */
++ cuckoo_hash_entry *table1;
++} cuckoo_hash_table;
++
++/*! Initialise the cuckoo has table
++ *
++ * \param hashtab A pointer to an unitialised hash table structure
++ * \param length_bits The number of elements in each table equals
++ * 2**length_bits
++ * \param key_length The length of the key in bytes
++ *
++ * \return 0 on success, -ENOMEM if it couldn't allocate the tables
++ */
++extern
++int cuckoo_hash_init(cuckoo_hash_table *hashtab, unsigned length_bits,
++ unsigned key_length);
++
++
++/*! Destroy a hash table
++ *
++ * \param hashtab A hash table that has previously been passed to a
++ * successful call of cuckoo_hash_init()
++ */
++extern
++void cuckoo_hash_destroy(cuckoo_hash_table *hashtab);
++
++
++/*! Lookup an entry in the hash table
++ *
++ * \param hashtab The hash table in which to look.
++ * \param key Pointer to a mac address to use as the key
++ * \param value On exit set to the value stored if key was present
++ *
++ * \return 0 if not present in the table, non-zero if it is (and value
++ * is set accordingly)
++ */
++extern
++int cuckoo_hash_lookup(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key,
++ cuckoo_hash_value *value);
++
++/*! Add an entry to the hash table. Key must not be a duplicate of
++ * anything already in the table. If this is a risk, see
++ * cuckoo_hash_add_check
++ *
++ * \param hashtab The hash table to add the entry to
++ * \param key Pointer to a mac address to use as a key
++ * \param value The value to store
++ * \param can_rehash Flag to allow the add function to rehash the
++ * table if necessary
++ *
++ * \return 0 on success, non-zero on failure. -ENOSPC means it just
++ * couldn't find anywhere to put it - this is bad and probably means
++ * an entry has been dropped on the floor (but the entry you just
++ * tried to add may now be included)
++ */
++extern
++int cuckoo_hash_add(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key,
++ cuckoo_hash_value value,
++ int can_rehash);
++
++/*! Same as cuckoo_hash_add but first checks to ensure entry is not
++ * already there
++ * \return -EBUSY if already there
++ */
++
++extern
++int cuckoo_hash_add_check(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key,
++ cuckoo_hash_value value,
++ int can_rehash);
++/*! Remove an entry from the table
++ *
++ * \param hashtab The hash table to remove the entry from
++ * \param key The key that was used to previously add the entry
++ *
++ * \return 0 on success, -EINVAL if the entry couldn't be found
++ */
++extern
++int cuckoo_hash_remove(cuckoo_hash_table *hashtab, cuckoo_hash_key *key);
++
++
++/*! Helper for those using mac addresses to convert to a key for the
++ * hash table
++ */
++static inline cuckoo_hash_mac_key cuckoo_mac_to_key(const u8 *mac)
++{
++ return (cuckoo_hash_mac_key)(mac[0])
++ | (cuckoo_hash_mac_key)(mac[1]) << 8
++ | (cuckoo_hash_mac_key)(mac[2]) << 16
++ | (cuckoo_hash_mac_key)(mac[3]) << 24
++ | (cuckoo_hash_mac_key)(mac[4]) << 32
++ | (cuckoo_hash_mac_key)(mac[5]) << 40;
++}
++
++
++/*! Update an entry already in the hash table to take a new value
++ *
++ * \param hashtab The hash table to add the entry to
++ * \param key Pointer to a mac address to use as a key
++ * \param value The value to store
++ *
++ * \return 0 on success, non-zero on failure.
++ */
++int cuckoo_hash_update(cuckoo_hash_table *hashtab, cuckoo_hash_key *key,
++ cuckoo_hash_value value);
++
++
++/*! Go through the hash table and return all used entries (one per call)
++ *
++ * \param hashtab The hash table to iterate over
++ * \param key Pointer to a key to take the returned key
++ * \param value Pointer to a value to take the returned value
++ *
++ * \return 0 on success (key, value set), non-zero on failure.
++ */
++int cuckoo_hash_iterate(cuckoo_hash_table *hashtab,
++ cuckoo_hash_key *key, cuckoo_hash_value *value);
++void cuckoo_hash_iterate_reset(cuckoo_hash_table *hashtab);
++
++/* debug, not compiled by default */
++void cuckoo_hash_valid(cuckoo_hash_table *hashtab);
++void cuckoo_hash_dump(cuckoo_hash_table *hashtab);
++
++#endif /* NET_ACCEL_CUCKOO_HASH_H */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netutil/accel_msg_iface.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_msg_iface.c
+--- linux-2.6.18.8/drivers/xen/sfc_netutil/accel_msg_iface.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_msg_iface.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,301 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <xen/evtchn.h>
++
++#include "accel_util.h"
++#include "accel_msg_iface.h"
++
++#define NET_ACCEL_MSG_Q_SIZE (1024)
++#define NET_ACCEL_MSG_Q_MASK (NET_ACCEL_MSG_Q_SIZE - 1)
++
++#ifdef NDEBUG
++#define NET_ACCEL_CHECK_MAGIC(_p, _errval)
++#define NET_ACCEL_SHOW_QUEUE(_t, _q, _id)
++#else
++#define NET_ACCEL_CHECK_MAGIC(_p, _errval) \
++ if (_p->magic != NET_ACCEL_MSG_MAGIC) { \
++ printk(KERN_ERR "%s: passed invalid shared page %p!\n", \
++ __FUNCTION__, _p); \
++ return _errval; \
++ }
++#define NET_ACCEL_SHOW_QUEUE(_t, _q, _id) \
++ printk(_t ": queue %d write %x read %x base %x limit %x\n", \
++ _id, _q->write, _q->read, _q->base, _q->limit);
++#endif
++
++/*
++ * We've been passed at least 2 pages. 1 control page and 1 or more
++ * data pages.
++ */
++int net_accel_msg_init_page(void *mem, int len, int up)
++{
++ struct net_accel_shared_page *shared_page =
++ (struct net_accel_shared_page*)mem;
++
++ if ((unsigned long)shared_page & NET_ACCEL_MSG_Q_MASK)
++ return -EINVAL;
++
++ shared_page->magic = NET_ACCEL_MSG_MAGIC;
++
++ shared_page->aflags = 0;
++
++ shared_page->net_dev_up = up;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_init_page);
++
++
++void net_accel_msg_init_queue(sh_msg_fifo2 *queue,
++ struct net_accel_msg_queue *indices,
++ struct net_accel_msg *base, int size)
++{
++ queue->fifo = base;
++ spin_lock_init(&queue->lock);
++ sh_fifo2_init(queue, size-1, &indices->read, &indices->write);
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_init_queue);
++
++
++static inline int _net_accel_msg_send(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ struct net_accel_msg *msg,
++ int is_reply)
++{
++ int rc = 0;
++ NET_ACCEL_CHECK_MAGIC(sp, -EINVAL);
++ rmb();
++ if (is_reply) {
++ EPRINTK_ON(sh_fifo2_is_full(queue));
++ sh_fifo2_put(queue, *msg);
++ } else {
++ if (sh_fifo2_not_half_full(queue)) {
++ sh_fifo2_put(queue, *msg);
++ } else {
++ rc = -ENOSPC;
++ }
++ }
++ wmb();
++ return rc;
++}
++
++/* Notify after a batch of messages have been sent */
++void net_accel_msg_notify(int irq)
++{
++ notify_remote_via_irq(irq);
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_notify);
++
++/*
++ * Send a message on the specified FIFO. Returns 0 on success, -errno
++ * on failure. The message in msg is copied to the current slot of the
++ * FIFO.
++ */
++int net_accel_msg_send(struct net_accel_shared_page *sp, sh_msg_fifo2 *q,
++ struct net_accel_msg *msg)
++{
++ unsigned long flags;
++ int rc;
++ net_accel_msg_lock_queue(q, &flags);
++ rc = _net_accel_msg_send(sp, q, msg, 0);
++ net_accel_msg_unlock_queue(q, &flags);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_send);
++
++
++/* As net_accel_msg_send but also posts a notification to the far end. */
++int net_accel_msg_send_notify(struct net_accel_shared_page *sp, int irq,
++ sh_msg_fifo2 *q, struct net_accel_msg *msg)
++{
++ unsigned long flags;
++ int rc;
++ net_accel_msg_lock_queue(q, &flags);
++ rc = _net_accel_msg_send(sp, q, msg, 0);
++ net_accel_msg_unlock_queue(q, &flags);
++ if (rc >= 0)
++ notify_remote_via_irq(irq);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_send_notify);
++
++
++int net_accel_msg_reply(struct net_accel_shared_page *sp, sh_msg_fifo2 *q,
++ struct net_accel_msg *msg)
++{
++ unsigned long flags;
++ int rc;
++ net_accel_msg_lock_queue(q, &flags);
++ rc = _net_accel_msg_send(sp, q, msg, 1);
++ net_accel_msg_unlock_queue(q, &flags);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_reply);
++
++
++/* As net_accel_msg_send but also posts a notification to the far end. */
++int net_accel_msg_reply_notify(struct net_accel_shared_page *sp, int irq,
++ sh_msg_fifo2 *q, struct net_accel_msg *msg)
++{
++ unsigned long flags;
++ int rc;
++ net_accel_msg_lock_queue(q, &flags);
++ rc = _net_accel_msg_send(sp, q, msg, 1);
++ net_accel_msg_unlock_queue(q, &flags);
++ if (rc >= 0)
++ notify_remote_via_irq(irq);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_reply_notify);
++
++
++/*
++ * Look at a received message, if any, so a decision can be made about
++ * whether to read it now or not. Cookie is a bit of debug which is
++ * set here and checked when passed to net_accel_msg_recv_next()
++ */
++int net_accel_msg_peek(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ struct net_accel_msg *msg, int *cookie)
++{
++ unsigned long flags;
++ int rc = 0;
++ NET_ACCEL_CHECK_MAGIC(sp, -EINVAL);
++ net_accel_msg_lock_queue(queue, &flags);
++ rmb();
++ if (sh_fifo2_is_empty(queue)) {
++ rc = -ENOENT;
++ } else {
++ *msg = sh_fifo2_peek(queue);
++ *cookie = *(queue->fifo_rd_i);
++ }
++ net_accel_msg_unlock_queue(queue, &flags);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_peek);
++
++
++/*
++ * Move the queue onto the next element, used after finished with a
++ * peeked msg
++ */
++int net_accel_msg_recv_next(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue, int cookie)
++{
++ unsigned long flags;
++ NET_ACCEL_CHECK_MAGIC(sp, -EINVAL);
++ net_accel_msg_lock_queue(queue, &flags);
++ rmb();
++ /* Mustn't be empty */
++ BUG_ON(sh_fifo2_is_empty(queue));
++ /*
++ * Check cookie matches, i.e. we're advancing over the same message
++ * as was got using peek
++ */
++ BUG_ON(cookie != *(queue->fifo_rd_i));
++ sh_fifo2_rd_next(queue);
++ wmb();
++ net_accel_msg_unlock_queue(queue, &flags);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_recv_next);
++
++
++/*
++ * Receive a message on the specified FIFO. Returns 0 on success,
++ * -errno on failure.
++ */
++int net_accel_msg_recv(struct net_accel_shared_page *sp, sh_msg_fifo2 *queue,
++ struct net_accel_msg *msg)
++{
++ unsigned long flags;
++ int rc = 0;
++ NET_ACCEL_CHECK_MAGIC(sp, -EINVAL);
++ net_accel_msg_lock_queue(queue, &flags);
++ rmb();
++ if (sh_fifo2_is_empty(queue)) {
++ rc = -ENOENT;
++ } else {
++ sh_fifo2_get(queue, msg);
++ }
++ wmb();
++ net_accel_msg_unlock_queue(queue, &flags);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_recv);
++
++
++/*
++ * Start sending a message without copying. returns a pointer to a message
++ * that will be filled out in place. The queue is locked until the message
++ * is sent.
++ */
++struct net_accel_msg *net_accel_msg_start_send(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue, unsigned long *flags)
++{
++ struct net_accel_msg *msg;
++ NET_ACCEL_CHECK_MAGIC(sp, NULL);
++ net_accel_msg_lock_queue(queue, flags);
++ rmb();
++ if (sh_fifo2_not_half_full(queue)) {
++ msg = sh_fifo2_pokep(queue);
++ } else {
++ net_accel_msg_unlock_queue(queue, flags);
++ msg = NULL;
++ }
++ return msg;
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_start_send);
++
++
++static inline void _msg_complete(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ unsigned long *flags)
++{
++ sh_fifo2_wr_next(queue);
++ net_accel_msg_unlock_queue(queue, flags);
++}
++
++/*
++ * Complete the sending of a message started with net_accel_msg_start_send. The
++ * message is implicit since the queue was locked by _start
++ */
++void net_accel_msg_complete_send(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ unsigned long *flags)
++{
++ _msg_complete(sp, queue, flags);
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_complete_send);
++
++/* As net_accel_msg_complete_send but does the notify. */
++void net_accel_msg_complete_send_notify(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ unsigned long *flags, int irq)
++{
++ _msg_complete(sp, queue, flags);
++ notify_remote_via_irq(irq);
++}
++EXPORT_SYMBOL_GPL(net_accel_msg_complete_send_notify);
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netutil/accel_msg_iface.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_msg_iface.h
+--- linux-2.6.18.8/drivers/xen/sfc_netutil/accel_msg_iface.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_msg_iface.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,414 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NET_ACCEL_MSG_IFACE_H
++#define NET_ACCEL_MSG_IFACE_H
++
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <linux/in.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++
++#include "accel_shared_fifo.h"
++
++#define NET_ACCEL_MSG_MAGIC (0x85465479)
++
++/*! We talk version 0.010 of the interdomain protocol */
++#define NET_ACCEL_MSG_VERSION (0x00001000)
++
++/*! Shared memory portion of inter-domain FIFO */
++struct net_accel_msg_queue {
++ u32 read;
++ u32 write;
++};
++
++
++/*
++ * The aflags in the following structure is used as follows:
++ *
++ * - each bit is set when one of the corresponding variables is
++ * changed by either end.
++ *
++ * - the end that has made the change then forwards an IRQ to the
++ * other
++ *
++ * - the IRQ handler deals with these bits either on the fast path, or
++ * for less common changes, by jumping onto the slow path.
++ *
++ * - once it has seen a change, it clears the relevant bit.
++ *
++ * aflags is accessed atomically using clear_bit, test_bit,
++ * test_and_set_bit etc
++ */
++
++/*
++ * The following used to signify to the other domain when the queue
++ * they want to use is full, and when it is no longer full. Could be
++ * compressed to use fewer bits but done this way for simplicity and
++ * clarity
++ */
++
++/* "dom0->domU queue" is full */
++#define NET_ACCEL_MSG_AFLAGS_QUEUE0FULL 0x1
++#define NET_ACCEL_MSG_AFLAGS_QUEUE0FULL_B 0
++/* "dom0->domU queue" is not full */
++#define NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL 0x2
++#define NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL_B 1
++/* "domU->dom0 queue" is full */
++#define NET_ACCEL_MSG_AFLAGS_QUEUEUFULL 0x4
++#define NET_ACCEL_MSG_AFLAGS_QUEUEUFULL_B 2
++/* "domU->dom0 queue" is not full */
++#define NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL 0x8
++#define NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL_B 3
++/* dom0 -> domU net_dev up/down events */
++#define NET_ACCEL_MSG_AFLAGS_NETUPDOWN 0x10
++#define NET_ACCEL_MSG_AFLAGS_NETUPDOWN_B 4
++
++/*
++ * Masks used to test if there are any messages for domU and dom0
++ * respectively
++ */
++#define NET_ACCEL_MSG_AFLAGS_TO_DOMU_MASK \
++ (NET_ACCEL_MSG_AFLAGS_QUEUE0FULL | \
++ NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL | \
++ NET_ACCEL_MSG_AFLAGS_NETUPDOWN)
++#define NET_ACCEL_MSG_AFLAGS_TO_DOM0_MASK \
++ (NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL | \
++ NET_ACCEL_MSG_AFLAGS_QUEUEUFULL)
++
++/*! The shared data structure used for inter-VM communication. */
++struct net_accel_shared_page {
++ /*! Sanity check */
++ u32 magic;
++ /*! Used by host/Dom0 */
++ struct net_accel_msg_queue queue0;
++ /*! Used by guest/DomU */
++ struct net_accel_msg_queue queue1;
++ /*! Atomic flags, used to communicate simple state changes */
++ u32 aflags;
++ /*! State of net_dev used for acceleration */
++ u32 net_dev_up;
++};
++
++
++enum net_accel_hw_type {
++ /*! Not a virtualisable NIC: use slow path. */
++ NET_ACCEL_MSG_HWTYPE_NONE = 0,
++ /*! NIC is Falcon-based */
++ NET_ACCEL_MSG_HWTYPE_FALCON_A = 1,
++ NET_ACCEL_MSG_HWTYPE_FALCON_B = 2,
++};
++
++/*! The maximum number of pages used by an event queue. */
++#define EF_HW_FALCON_EVQ_PAGES 8
++
++struct net_accel_hw_falcon_b {
++ /* VI */
++ /*! Grant for Tx DMA Q */
++ u32 txdmaq_gnt;
++ /*! Grant for Rx DMA Q */
++ u32 rxdmaq_gnt;
++ /*! Machine frame number for Tx/Rx doorbell page */
++ u32 doorbell_mfn;
++ /*! Grant for Tx/Rx doorbell page */
++ u32 doorbell_gnt;
++
++ /* Event Q */
++ /*! Grants for the pages of the EVQ */
++ u32 evq_mem_gnts[EF_HW_FALCON_EVQ_PAGES];
++ u32 evq_offs;
++ /*! log2(pages in event Q) */
++ u32 evq_order;
++ /*! Capacity in events */
++ u32 evq_capacity;
++ /*! Eventq pointer register physical address */
++ u32 evq_rptr;
++ /*! Interface instance */
++ u32 instance;
++ /*! Capacity of RX queue */
++ u32 rx_capacity;
++ /*! Capacity of TX queue */
++ u32 tx_capacity;
++
++ /* NIC */
++ s32 nic_arch;
++ s32 nic_revision;
++ u8 nic_variant;
++};
++
++struct net_accel_hw_falcon_a {
++ struct net_accel_hw_falcon_b common;
++ u32 evq_rptr_gnt;
++};
++
++
++/*! Description of the hardware that the DomU is being given. */
++struct net_accel_msg_hw {
++ u32 type; /*!< Hardware type */
++ union {
++ struct net_accel_hw_falcon_a falcon_a;
++ struct net_accel_hw_falcon_b falcon_b;
++ } resources;
++};
++
++/*! Start-of-day handshake message. Dom0 fills in its version and
++ * sends, DomU checks, inserts its version and replies
++ */
++struct net_accel_msg_hello {
++ /*! Sender's version (set by each side in turn) */
++ u32 version;
++ /*! max pages allocated/allowed for buffers */
++ u32 max_pages;
++};
++
++/*! Maximum number of page requests that can fit in a message. */
++#define NET_ACCEL_MSG_MAX_PAGE_REQ (8)
++
++/*! Request for NIC buffers. DomU fils out pages and grants (and
++ * optionally) reqid, dom0 fills out buf and sends reply
++ */
++struct net_accel_msg_map_buffers {
++ u32 reqid; /*!< Optional request ID */
++ u32 pages; /*!< Number of pages to map */
++ u32 grants[NET_ACCEL_MSG_MAX_PAGE_REQ]; /*!< Grant ids to map */
++ u32 buf; /*!< NIC buffer address of pages obtained */
++};
++
++/*! Notification of a change to local mac address, used to filter
++ locally destined packets off the fast path */
++struct net_accel_msg_localmac {
++ u32 flags; /*!< Should this be added or removed? */
++ u8 mac[ETH_ALEN]; /*!< The mac address to filter onto slow path */
++};
++
++struct net_accel_msg_fastpath {
++ u32 flags; /*!< Should this be added or removed? */
++ u8 mac[ETH_ALEN];/*!< The mac address to filter onto fast path */
++ u16 port; /*!< The port of the connection */
++ u32 ip; /*!< The IP address of the connection */
++ u8 proto; /*!< The protocol of connection (TCP/UDP) */
++};
++
++/*! Values for struct ef_msg_localmac/fastpath.flags */
++#define NET_ACCEL_MSG_ADD 0x1
++#define NET_ACCEL_MSG_REMOVE 0x2
++
++/*! Overall message structure */
++struct net_accel_msg {
++ /*! ID specifying type of messge */
++ u32 id;
++ union {
++ /*! handshake */
++ struct net_accel_msg_hello hello;
++ /*! hardware description */
++ struct net_accel_msg_hw hw;
++ /*! buffer map request */
++ struct net_accel_msg_map_buffers mapbufs;
++ /*! mac address of a local interface */
++ struct net_accel_msg_localmac localmac;
++ /*! address of a new fastpath connection */
++ struct net_accel_msg_fastpath fastpath;
++ /*! make the message a fixed size */
++ u8 pad[128 - sizeof(u32)];
++ } u;
++};
++
++
++#define NET_ACCEL_MSG_HW_TO_MSG(_u) container_of(_u, struct net_accel_msg, u.hw)
++
++/*! Inter-domain message FIFO */
++typedef struct {
++ struct net_accel_msg *fifo;
++ u32 fifo_mask;
++ u32 *fifo_rd_i;
++ u32 *fifo_wr_i;
++ spinlock_t lock;
++ u32 is_locked; /* Debug flag */
++} sh_msg_fifo2;
++
++
++#define NET_ACCEL_MSG_OFFSET_MASK PAGE_MASK
++
++/* Modifiers */
++#define NET_ACCEL_MSG_REPLY (0x80000000)
++#define NET_ACCEL_MSG_ERROR (0x40000000)
++
++/* Dom0 -> DomU and reply. Handshake/version check. */
++#define NET_ACCEL_MSG_HELLO (0x00000001)
++/* Dom0 -> DomU : hardware setup (VI info.) */
++#define NET_ACCEL_MSG_SETHW (0x00000002)
++/*
++ * Dom0 -> DomU. Notification of a local mac to add/remove from slow
++ * path filter
++ */
++#define NET_ACCEL_MSG_LOCALMAC (0x00000003)
++/*
++ * DomU -> Dom0 and reply. Request for buffer table entries for
++ * preallocated pages.
++ */
++#define NET_ACCEL_MSG_MAPBUF (0x00000004)
++/*
++ * Dom0 -> DomU. Notification of a local mac to add/remove from fast
++ * path filter
++ */
++#define NET_ACCEL_MSG_FASTPATH (0x00000005)
++
++/*! Initialise a message and set the type
++ * \param message : the message
++ * \param code : the message type
++ */
++static inline void net_accel_msg_init(struct net_accel_msg *msg, int code) {
++ msg->id = (u32)code;
++}
++
++/*! initialise a shared page structure
++ * \param shared_page : mapped memory in which the structure resides
++ * \param len : size of the message FIFO area that follows
++ * \param up : initial up/down state of netdev
++ * \return 0 or an error code
++ */
++extern int net_accel_msg_init_page(void *shared_page, int len, int up);
++
++/*! initialise a message queue
++ * \param queue : the message FIFO to initialise
++ * \param indices : the read and write indices in shared memory
++ * \param base : the start of the memory area for the FIFO
++ * \param size : the size of the FIFO in bytes
++ */
++extern void net_accel_msg_init_queue(sh_msg_fifo2 *queue,
++ struct net_accel_msg_queue *indices,
++ struct net_accel_msg *base, int size);
++
++/* Notify after a batch of messages have been sent */
++extern void net_accel_msg_notify(int irq);
++
++/*! Send a message on the specified FIFO. The message is copied to the
++ * current slot of the FIFO.
++ * \param sp : pointer to shared page
++ * \param q : pointer to message FIFO to use
++ * \param msg : pointer to message
++ * \return 0 on success, -errno on
++ */
++extern int net_accel_msg_send(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *q,
++ struct net_accel_msg *msg);
++extern int net_accel_msg_reply(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *q,
++ struct net_accel_msg *msg);
++
++/*! As net_accel_msg_send but also posts a notification to the far end. */
++extern int net_accel_msg_send_notify(struct net_accel_shared_page *sp,
++ int irq, sh_msg_fifo2 *q,
++ struct net_accel_msg *msg);
++/*! As net_accel_msg_send but also posts a notification to the far end. */
++extern int net_accel_msg_reply_notify(struct net_accel_shared_page *sp,
++ int irq, sh_msg_fifo2 *q,
++ struct net_accel_msg *msg);
++
++/*! Receive a message on the specified FIFO. Returns 0 on success,
++ * -errno on failure.
++ */
++extern int net_accel_msg_recv(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *q,
++ struct net_accel_msg *msg);
++
++/*! Look at a received message, if any, so a decision can be made
++ * about whether to read it now or not. Cookie is a bit of debug
++ * which is set here and checked when passed to
++ * net_accel_msg_recv_next()
++ */
++extern int net_accel_msg_peek(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ struct net_accel_msg *msg, int *cookie);
++/*! Move the queue onto the next element, used after finished with a
++ * peeked msg
++ */
++extern int net_accel_msg_recv_next(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue, int cookie);
++
++/*! Start sending a message without copying. returns a pointer to a
++ * message that will be filled out in place. The queue is locked
++ * until the message is sent.
++ */
++extern
++struct net_accel_msg *net_accel_msg_start_send(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ unsigned long *flags);
++
++
++/*! Complete the sending of a message started with
++ * net_accel_msg_start_send. The message is implicit since the queue
++ * was locked by _start
++ */
++extern void net_accel_msg_complete_send(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ unsigned long *flags);
++
++/*! As net_accel_msg_complete_send but does the notify. */
++extern void net_accel_msg_complete_send_notify(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue,
++ unsigned long *flags, int irq);
++
++/*! Lock the queue so that multiple "_locked" functions can be called
++ * without the queue being modified by others
++ */
++static inline
++void net_accel_msg_lock_queue(sh_msg_fifo2 *queue, unsigned long *flags)
++{
++ spin_lock_irqsave(&queue->lock, (*flags));
++ rmb();
++ BUG_ON(queue->is_locked);
++ queue->is_locked = 1;
++}
++
++/*! Unlock the queue */
++static inline
++void net_accel_msg_unlock_queue(sh_msg_fifo2 *queue, unsigned long *flags)
++{
++ BUG_ON(!queue->is_locked);
++ queue->is_locked = 0;
++ wmb();
++ spin_unlock_irqrestore(&queue->lock, (*flags));
++}
++
++/*! Give up without sending a message that was started with
++ * net_accel_msg_start_send()
++ */
++static inline
++void net_accel_msg_abort_send(struct net_accel_shared_page *sp,
++ sh_msg_fifo2 *queue, unsigned long *flags)
++{
++ net_accel_msg_unlock_queue(queue, flags);
++}
++
++/*! Test the queue to ensure there is sufficient space */
++static inline
++int net_accel_msg_check_space(sh_msg_fifo2 *queue, unsigned space)
++{
++ return sh_fifo2_space(queue) >= space;
++}
++
++#endif /* NET_ACCEL_MSG_IFACE_H */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netutil/accel_shared_fifo.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_shared_fifo.h
+--- linux-2.6.18.8/drivers/xen/sfc_netutil/accel_shared_fifo.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_shared_fifo.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,127 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NET_ACCEL_SHARED_FIFO_H
++#define NET_ACCEL_SHARED_FIFO_H
++
++/*
++ * This is based on fifo.h, but handles sharing between address spaces
++ * that don't trust each other, by splitting out the read and write
++ * indices. This costs at least one pointer indirection more than the
++ * vanilla version per access.
++ */
++
++typedef struct {
++ char* fifo;
++ unsigned fifo_mask;
++ unsigned *fifo_rd_i;
++ unsigned *fifo_wr_i;
++} sh_byte_fifo2;
++
++#define SH_FIFO2_M(f, x) ((x) & ((f)->fifo_mask))
++
++static inline unsigned log2_ge(unsigned long n, unsigned min_order) {
++ unsigned order = min_order;
++ while((1ul << order) < n) ++order;
++ return order;
++}
++
++static inline unsigned long pow2(unsigned order) {
++ return (1ul << order);
++}
++
++#define is_pow2(x) (pow2(log2_ge((x), 0)) == (x))
++
++#define sh_fifo2_valid(f) ((f) && (f)->fifo && (f)->fifo_mask > 0 && \
++ is_pow2((f)->fifo_mask+1u))
++
++#define sh_fifo2_init(f, cap, _rptr, _wptr) \
++ do { \
++ BUG_ON(!is_pow2((cap) + 1)); \
++ (f)->fifo_rd_i = _rptr; \
++ (f)->fifo_wr_i = _wptr; \
++ *(f)->fifo_rd_i = *(f)->fifo_wr_i = 0u; \
++ (f)->fifo_mask = (cap); \
++ } while(0)
++
++#define sh_fifo2_num(f) SH_FIFO2_M((f),*(f)->fifo_wr_i - *(f)->fifo_rd_i)
++#define sh_fifo2_space(f) SH_FIFO2_M((f),*(f)->fifo_rd_i - *(f)->fifo_wr_i-1u)
++#define sh_fifo2_is_empty(f) (sh_fifo2_num(f)==0)
++#define sh_fifo2_not_empty(f) (sh_fifo2_num(f)!=0)
++#define sh_fifo2_is_full(f) (sh_fifo2_space(f)==0u)
++#define sh_fifo2_not_full(f) (sh_fifo2_space(f)!=0u)
++#define sh_fifo2_buf_size(f) ((f)->fifo_mask + 1u)
++#define sh_fifo2_capacity(f) ((f)->fifo_mask)
++#define sh_fifo2_end(f) ((f)->fifo + sh_fifo2_buf_size(f))
++#define sh_fifo2_not_half_full(f) (sh_fifo2_space(f) > (sh_fifo2_capacity(f) >> 1))
++
++#define sh_fifo2_peek(f) ((f)->fifo[SH_FIFO2_M((f), *(f)->fifo_rd_i)])
++#define sh_fifo2_peekp(f) ((f)->fifo + SH_FIFO2_M((f), *(f)->fifo_rd_i))
++#define sh_fifo2_poke(f) ((f)->fifo[SH_FIFO2_M((f), *(f)->fifo_wr_i)])
++#define sh_fifo2_pokep(f) ((f)->fifo + SH_FIFO2_M((f), *(f)->fifo_wr_i))
++#define sh_fifo2_peek_i(f,i) ((f)->fifo[SH_FIFO2_M((f), *(f)->fifo_rd_i+(i))])
++#define sh_fifo2_poke_i(f,i) ((f)->fifo[SH_FIFO2_M((f), *(f)->fifo_wr_i+(i))])
++
++#define sh_fifo2_rd_next(f) \
++ do {*(f)->fifo_rd_i = *(f)->fifo_rd_i + 1u;} while(0)
++#define sh_fifo2_wr_next(f) \
++ do {*(f)->fifo_wr_i = *(f)->fifo_wr_i + 1u;} while(0)
++#define sh_fifo2_rd_adv(f, n) \
++ do {*(f)->fifo_rd_i = *(f)->fifo_rd_i + (n);} while(0)
++#define sh_fifo2_wr_adv(f, n) \
++ do {*(f)->fifo_wr_i = *(f)->fifo_wr_i + (n);} while(0)
++
++#define sh_fifo2_put(f, v) \
++ do {sh_fifo2_poke(f) = (v); wmb(); sh_fifo2_wr_next(f);} while(0)
++
++#define sh_fifo2_get(f, pv) \
++ do {*(pv) = sh_fifo2_peek(f); mb(); sh_fifo2_rd_next(f);} while(0)
++
++static inline unsigned sh_fifo2_contig_num(sh_byte_fifo2 *f)
++{
++ unsigned fifo_wr_i = SH_FIFO2_M(f, *f->fifo_wr_i);
++ unsigned fifo_rd_i = SH_FIFO2_M(f, *f->fifo_rd_i);
++
++ return (fifo_wr_i >= fifo_rd_i)
++ ? fifo_wr_i - fifo_rd_i
++ : f->fifo_mask + 1u - *(f)->fifo_rd_i;
++}
++
++static inline unsigned sh_fifo2_contig_space(sh_byte_fifo2 *f)
++{
++ unsigned fifo_wr_i = SH_FIFO2_M(f, *f->fifo_wr_i);
++ unsigned fifo_rd_i = SH_FIFO2_M(f, *f->fifo_rd_i);
++
++ return (fifo_rd_i > fifo_wr_i)
++ ? fifo_rd_i - fifo_wr_i - 1
++ : (f->fifo_mask + 1u - fifo_wr_i
++ /*
++ * The last byte can't be used if the read pointer
++ * is at zero.
++ */
++ - (fifo_rd_i==0));
++}
++
++
++#endif /* NET_ACCEL_SHARED_FIFO_H */
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netutil/accel_util.c linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_util.c
+--- linux-2.6.18.8/drivers/xen/sfc_netutil/accel_util.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_util.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,333 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#include <linux/if_ether.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/hypercall.h>
++#include <xen/xenbus.h>
++#include <xen/driver_util.h>
++#include <xen/gnttab.h>
++
++#include "accel_util.h"
++
++#ifdef EFX_GCOV
++#include "gcov.h"
++
++static int __init net_accel_init(void)
++{
++ gcov_provider_init(THIS_MODULE);
++ return 0;
++}
++module_init(net_accel_init);
++
++static void __exit net_accel_exit(void)
++{
++ gcov_provider_fini(THIS_MODULE);
++}
++module_exit(net_accel_exit);
++#endif
++
++/* Shutdown remote domain that is misbehaving */
++int net_accel_shutdown_remote(int domain)
++{
++ struct sched_remote_shutdown sched_shutdown = {
++ .domain_id = domain,
++ .reason = SHUTDOWN_crash
++ };
++
++ EPRINTK("Crashing domain %d\n", domain);
++
++ return HYPERVISOR_sched_op(SCHEDOP_remote_shutdown, &sched_shutdown);
++}
++EXPORT_SYMBOL(net_accel_shutdown_remote);
++
++
++/* Based on xenbus_backend_client.c:xenbus_map_ring() */
++static int net_accel_map_grant(struct xenbus_device *dev, int gnt_ref,
++ grant_handle_t *handle, void *vaddr,
++ u64 *dev_bus_addr, unsigned flags)
++{
++ struct gnttab_map_grant_ref op;
++
++ gnttab_set_map_op(&op, (unsigned long)vaddr, flags,
++ gnt_ref, dev->otherend_id);
++
++ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
++
++ if (op.status != GNTST_okay) {
++ xenbus_dev_error
++ (dev, op.status,
++ "failed mapping in shared page %d from domain %d\n",
++ gnt_ref, dev->otherend_id);
++ } else {
++ *handle = op.handle;
++ if (dev_bus_addr)
++ *dev_bus_addr = op.dev_bus_addr;
++ }
++
++ return op.status;
++}
++
++
++/* Based on xenbus_backend_client.c:xenbus_unmap_ring() */
++static int net_accel_unmap_grant(struct xenbus_device *dev,
++ grant_handle_t handle,
++ void *vaddr, u64 dev_bus_addr,
++ unsigned flags)
++{
++ struct gnttab_unmap_grant_ref op;
++
++ gnttab_set_unmap_op(&op, (unsigned long)vaddr, flags, handle);
++
++ if (dev_bus_addr)
++ op.dev_bus_addr = dev_bus_addr;
++
++ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
++
++ if (op.status != GNTST_okay)
++ xenbus_dev_error(dev, op.status,
++ "failed unmapping page at handle %d error %d\n",
++ handle, op.status);
++
++ return op.status;
++}
++
++
++int net_accel_map_device_page(struct xenbus_device *dev,
++ int gnt_ref, grant_handle_t *handle,
++ u64 *dev_bus_addr)
++{
++ return net_accel_map_grant(dev, gnt_ref, handle, 0, dev_bus_addr,
++ GNTMAP_device_map);
++}
++EXPORT_SYMBOL_GPL(net_accel_map_device_page);
++
++
++int net_accel_unmap_device_page(struct xenbus_device *dev,
++ grant_handle_t handle, u64 dev_bus_addr)
++{
++ return net_accel_unmap_grant(dev, handle, 0, dev_bus_addr,
++ GNTMAP_device_map);
++}
++EXPORT_SYMBOL_GPL(net_accel_unmap_device_page);
++
++
++struct net_accel_valloc_grant_mapping {
++ struct vm_struct *vm;
++ int pages;
++ grant_handle_t grant_handles[0];
++};
++
++/* Map a series of grants into a contiguous virtual area */
++static void *net_accel_map_grants_valloc(struct xenbus_device *dev,
++ unsigned *grants, int npages,
++ unsigned flags, void **priv)
++{
++ struct net_accel_valloc_grant_mapping *map;
++ struct vm_struct *vm;
++ void *addr;
++ int i, j, rc;
++
++ vm = alloc_vm_area(PAGE_SIZE * npages);
++ if (vm == NULL) {
++ EPRINTK("No memory from alloc_vm_area.\n");
++ return NULL;
++ }
++ /*
++ * Get a structure in which we will record all the info needed
++ * to undo the mapping.
++ */
++ map = kzalloc(sizeof(struct net_accel_valloc_grant_mapping) +
++ npages * sizeof(grant_handle_t), GFP_KERNEL);
++ if (map == NULL) {
++ EPRINTK("No memory for net_accel_valloc_grant_mapping\n");
++ free_vm_area(vm);
++ return NULL;
++ }
++ map->vm = vm;
++ map->pages = npages;
++
++ /* Do the actual mapping */
++ addr = vm->addr;
++ for (i = 0; i < npages; i++) {
++ rc = net_accel_map_grant(dev, grants[i], map->grant_handles + i,
++ addr, NULL, flags);
++ if (rc != 0)
++ goto undo;
++ addr = (void*)((unsigned long)addr + PAGE_SIZE);
++ }
++
++ if (priv)
++ *priv = (void *)map;
++ else
++ kfree(map);
++
++ return vm->addr;
++
++ undo:
++ EPRINTK("Aborting contig map due to single map failure %d (%d of %d)\n",
++ rc, i+1, npages);
++ for (j = 0; j < i; j++) {
++ addr = (void*)((unsigned long)vm->addr + (j * PAGE_SIZE));
++ net_accel_unmap_grant(dev, map->grant_handles[j], addr, 0,
++ flags);
++ }
++ free_vm_area(vm);
++ kfree(map);
++ return NULL;
++}
++
++/* Undo the result of the mapping */
++static void net_accel_unmap_grants_vfree(struct xenbus_device *dev,
++ unsigned flags, void *priv)
++{
++ struct net_accel_valloc_grant_mapping *map =
++ (struct net_accel_valloc_grant_mapping *)priv;
++
++ void *addr = map->vm->addr;
++ int npages = map->pages;
++ int i;
++
++ for (i = 0; i < npages; i++) {
++ net_accel_unmap_grant(dev, map->grant_handles[i], addr, 0,
++ flags);
++ addr = (void*)((unsigned long)addr + PAGE_SIZE);
++ }
++ free_vm_area(map->vm);
++ kfree(map);
++}
++
++
++void *net_accel_map_grants_contig(struct xenbus_device *dev,
++ unsigned *grants, int npages,
++ void **priv)
++{
++ return net_accel_map_grants_valloc(dev, grants, npages,
++ GNTMAP_host_map, priv);
++}
++EXPORT_SYMBOL(net_accel_map_grants_contig);
++
++
++void net_accel_unmap_grants_contig(struct xenbus_device *dev,
++ void *priv)
++{
++ net_accel_unmap_grants_vfree(dev, GNTMAP_host_map, priv);
++}
++EXPORT_SYMBOL(net_accel_unmap_grants_contig);
++
++
++void *net_accel_map_iomem_page(struct xenbus_device *dev, int gnt_ref,
++ void **priv)
++{
++ return net_accel_map_grants_valloc(dev, &gnt_ref, 1,
++ GNTMAP_host_map, priv);
++}
++EXPORT_SYMBOL(net_accel_map_iomem_page);
++
++
++void net_accel_unmap_iomem_page(struct xenbus_device *dev, void *priv)
++{
++ net_accel_unmap_grants_vfree(dev, GNTMAP_host_map, priv);
++}
++EXPORT_SYMBOL(net_accel_unmap_iomem_page);
++
++
++int net_accel_grant_page(struct xenbus_device *dev, unsigned long mfn,
++ int is_iomem)
++{
++ int err = gnttab_grant_foreign_access(dev->otherend_id, mfn,
++ is_iomem ? GTF_PCD : 0);
++ if (err < 0)
++ xenbus_dev_error(dev, err, "failed granting access to page\n");
++ return err;
++}
++EXPORT_SYMBOL_GPL(net_accel_grant_page);
++
++
++int net_accel_ungrant_page(grant_ref_t gntref)
++{
++ if (unlikely(gnttab_query_foreign_access(gntref) != 0)) {
++ EPRINTK("%s: remote domain still using grant %d\n", __FUNCTION__,
++ gntref);
++ return -EBUSY;
++ }
++
++ gnttab_end_foreign_access(gntref, 0);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(net_accel_ungrant_page);
++
++
++int net_accel_xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
++{
++ char *s, *e, *macstr;
++ int i;
++
++ macstr = s = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL);
++ if (IS_ERR(macstr))
++ return PTR_ERR(macstr);
++
++ for (i = 0; i < ETH_ALEN; i++) {
++ mac[i] = simple_strtoul(s, &e, 16);
++ if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
++ kfree(macstr);
++ return -ENOENT;
++ }
++ s = e+1;
++ }
++
++ kfree(macstr);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(net_accel_xen_net_read_mac);
++
++
++void net_accel_update_state(struct xenbus_device *dev, int state)
++{
++ struct xenbus_transaction tr;
++ int err;
++
++ DPRINTK("%s: setting accelstate to %s\n", __FUNCTION__,
++ xenbus_strstate(state));
++
++ if (xenbus_exists(XBT_NIL, dev->nodename, "")) {
++ VPRINTK("%s: nodename %s\n", __FUNCTION__, dev->nodename);
++ again:
++ err = xenbus_transaction_start(&tr);
++ if (err == 0)
++ err = xenbus_printf(tr, dev->nodename, "accelstate",
++ "%d", state);
++ if (err != 0) {
++ xenbus_transaction_end(tr, 1);
++ } else {
++ err = xenbus_transaction_end(tr, 0);
++ if (err == -EAGAIN)
++ goto again;
++ }
++ }
++}
++EXPORT_SYMBOL_GPL(net_accel_update_state);
++
++MODULE_LICENSE("GPL");
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netutil/accel_util.h linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_util.h
+--- linux-2.6.18.8/drivers/xen/sfc_netutil/accel_util.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/accel_util.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,127 @@
++/****************************************************************************
++ * Solarflare driver for Xen network acceleration
++ *
++ * Copyright 2006-2008: Solarflare Communications Inc,
++ * 9501 Jeronimo Road, Suite 250,
++ * Irvine, CA 92618, USA
++ *
++ * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ ****************************************************************************
++ */
++
++#ifndef NETBACK_ACCEL_UTIL_H
++#define NETBACK_ACCEL_UTIL_H
++
++#ifdef DPRINTK
++#undef DPRINTK
++#endif
++
++#define FILE_LEAF strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__
++
++#if 1
++#define VPRINTK(_f, _a...)
++#else
++#define VPRINTK(_f, _a...) \
++ printk("(file=%s, line=%d) " _f, \
++ FILE_LEAF , __LINE__ , ## _a )
++#endif
++
++#if 1
++#define DPRINTK(_f, _a...)
++#else
++#define DPRINTK(_f, _a...) \
++ printk("(file=%s, line=%d) " _f, \
++ FILE_LEAF , __LINE__ , ## _a )
++#endif
++
++#define EPRINTK(_f, _a...) \
++ printk("(file=%s, line=%d) " _f, \
++ FILE_LEAF , __LINE__ , ## _a )
++
++#define EPRINTK_ON(exp) \
++ do { \
++ if (exp) \
++ EPRINTK("%s at %s:%d\n", #exp, __FILE__, __LINE__); \
++ } while(0)
++
++#define DPRINTK_ON(exp) \
++ do { \
++ if (exp) \
++ DPRINTK("%s at %s:%d\n", #exp, __FILE__, __LINE__); \
++ } while(0)
++
++#define MAC_FMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
++#define MAC_ARG(_mac) (_mac)[0], (_mac)[1], (_mac)[2], (_mac)[3], (_mac)[4], (_mac)[5]
++
++#include <xen/xenbus.h>
++
++/*! Map a set of pages from another domain
++ * \param dev The xenbus device context
++ * \param priv The private data returned by the mapping function
++ */
++extern
++void *net_accel_map_grants_contig(struct xenbus_device *dev,
++ unsigned *grants, int npages,
++ void **priv);
++
++/*! Unmap a set of pages mapped using net_accel_map_grants_contig.
++ * \param dev The xenbus device context
++ * \param priv The private data returned by the mapping function
++ */
++extern
++void net_accel_unmap_grants_contig(struct xenbus_device *dev, void *priv);
++
++/*! Read the MAC address of a device from xenstore */
++extern
++int net_accel_xen_net_read_mac(struct xenbus_device *dev, u8 mac[]);
++
++/*! Update the accelstate field for a device in xenstore */
++extern
++void net_accel_update_state(struct xenbus_device *dev, int state);
++
++/* These four map/unmap functions are based on
++ * xenbus_backend_client.c:xenbus_map_ring(). However, they are not
++ * used for ring buffers, instead just to map pages between domains,
++ * or to map a page so that it is accessible by a device
++ */
++extern
++int net_accel_map_device_page(struct xenbus_device *dev,
++ int gnt_ref, grant_handle_t *handle,
++ u64 *dev_bus_addr);
++extern
++int net_accel_unmap_device_page(struct xenbus_device *dev,
++ grant_handle_t handle, u64 dev_bus_addr);
++extern
++void *net_accel_map_iomem_page(struct xenbus_device *dev, int gnt_ref,
++ void **priv);
++extern
++void net_accel_unmap_iomem_page(struct xenbus_device *dev, void *priv);
++
++/*! Grrant a page to remote domain */
++extern
++int net_accel_grant_page(struct xenbus_device *dev, unsigned long mfn,
++ int is_iomem);
++/*! Undo a net_accel_grant_page */
++extern
++int net_accel_ungrant_page(grant_ref_t gntref);
++
++
++/*! Shutdown remote domain that is misbehaving */
++extern
++int net_accel_shutdown_remote(int domain);
++
++
++#endif
+diff -rpuN linux-2.6.18.8/drivers/xen/sfc_netutil/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/Makefile
+--- linux-2.6.18.8/drivers/xen/sfc_netutil/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/sfc_netutil/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,11 @@
++EXTRA_CFLAGS += -Idrivers/xen/sfc_netutil
++EXTRA_CFLAGS += -Werror
++
++ifdef GGOV
++EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage -DEFX_GCOV
++endif
++
++obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL) := sfc_netutil.o
++
++sfc_netutil-objs := accel_cuckoo_hash.o accel_msg_iface.o accel_util.o
++
+diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/common.h linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/common.h
+--- linux-2.6.18.8/drivers/xen/tpmback/common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/common.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,85 @@
+/******************************************************************************
+ * drivers/xen/tpmback/common.h
@@ -103413,9 +171999,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/common.h linux-2.6.18-xen-3.2.0/dr
+}
+
+#endif /* __TPMIF__BACKEND__COMMON_H__ */
-diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/interface.c linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/interface.c
---- linux-2.6.18.8/drivers/xen/tpmback/interface.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/interface.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/interface.c linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/interface.c
+--- linux-2.6.18.8/drivers/xen/tpmback/interface.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/interface.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,168 @@
+ /*****************************************************************************
+ * drivers/xen/tpmback/interface.c
@@ -103585,9 +172171,17 @@ diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/interface.c linux-2.6.18-xen-3.2.0
+{
+ kmem_cache_destroy(tpmif_cachep);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/tpmback.c linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/tpmback.c
---- linux-2.6.18.8/drivers/xen/tpmback/tpmback.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/tpmback.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/Makefile
+--- linux-2.6.18.8/drivers/xen/tpmback/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/Makefile 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,4 @@
++
++obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmbk.o
++
++tpmbk-y += tpmback.o interface.o xenbus.o
+diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/tpmback.c linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/tpmback.c
+--- linux-2.6.18.8/drivers/xen/tpmback/tpmback.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/tpmback.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,944 @@
+/******************************************************************************
+ * drivers/xen/tpmback/tpmback.c
@@ -104533,9 +173127,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/tpmback.c linux-2.6.18-xen-3.2.0/d
+}
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/xenbus.c linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/xenbus.c
---- linux-2.6.18.8/drivers/xen/tpmback/xenbus.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/tpmback/xenbus.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/xenbus.c linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/xenbus.c
+--- linux-2.6.18.8/drivers/xen/tpmback/xenbus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/tpmback/xenbus.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,289 @@
+/* Xenbus code for tpmif backend
+ Copyright (C) 2005 IBM Corporation
@@ -104801,7 +173395,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+}
+
+
-+static struct xenbus_device_id tpmback_ids[] = {
++static const struct xenbus_device_id tpmback_ids[] = {
+ { "vtpm" },
+ { "" }
+};
@@ -104826,9 +173420,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/tpmback/xenbus.c linux-2.6.18-xen-3.2.0/dr
+{
+ xenbus_unregister_driver(&tpmback);
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/util.c linux-2.6.18-xen-3.2.0/drivers/xen/util.c
---- linux-2.6.18.8/drivers/xen/util.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/util.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/util.c linux-2.6.18-xen-3.3.0/drivers/xen/util.c
+--- linux-2.6.18.8/drivers/xen/util.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/util.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,65 @@
+#include <linux/mm.h>
+#include <linux/module.h>
@@ -104895,9 +173489,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/util.c linux-2.6.18-xen-3.2.0/drivers/xen/
+}
+EXPORT_SYMBOL_GPL(free_vm_area);
+#endif /* CONFIG_X86 */
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/Makefile linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/Makefile
---- linux-2.6.18.8/drivers/xen/xenbus/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/Makefile 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/Makefile linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/Makefile
+--- linux-2.6.18.8/drivers/xen/xenbus/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,9 @@
+obj-y += xenbus_client.o xenbus_comms.o xenbus_xs.o xenbus_probe.o
+obj-$(CONFIG_XEN_BACKEND) += xenbus_be.o
@@ -104908,9 +173502,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/Makefile linux-2.6.18-xen-3.2.0/dri
+xenbus-$(CONFIG_XEN_BACKEND) += xenbus_probe_backend.o
+obj-y += $(xenbus-y) $(xenbus-m)
+obj-$(CONFIG_XEN_XENBUS_DEV) += xenbus_dev.o
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_backend_client.c linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_backend_client.c
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_backend_client.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_backend_client.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_backend_client.c linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_backend_client.c
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_backend_client.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_backend_client.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,147 @@
+/******************************************************************************
+ * Backend-client-facing interface for the Xenbus driver. In other words, the
@@ -105059,9 +173653,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_backend_client.c linux-2.6.1
+EXPORT_SYMBOL_GPL(xenbus_dev_is_online);
+
+MODULE_LICENSE("Dual BSD/GPL");
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_client.c linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_client.c
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_client.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_client.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_client.c linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_client.c
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_client.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_client.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,284 @@
+/******************************************************************************
+ * Client-facing interface for the Xenbus driver. In other words, the
@@ -105152,7 +173746,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_client.c linux-2.6.18-xen-3.
+ const char **, unsigned int))
+{
+ int err;
-+ char *state = kasprintf(GFP_KERNEL|__GFP_HIGH, "%s/%s", path, path2);
++ char *state = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/%s", path, path2);
+ if (!state) {
+ xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
+ return -ENOMEM;
@@ -105347,9 +173941,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_client.c linux-2.6.18-xen-3.
+ return result;
+}
+EXPORT_SYMBOL_GPL(xenbus_read_driver_state);
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.c linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_comms.c
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_comms.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.c linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_comms.c
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_comms.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,233 @@
+/******************************************************************************
+ * xenbus_comms.c
@@ -105584,9 +174178,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.c linux-2.6.18-xen-3.2
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.h linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_comms.h
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_comms.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.h linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_comms.h
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_comms.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ * Private include for xenbus communications.
@@ -105634,10 +174228,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_comms.h linux-2.6.18-xen-3.2
+extern int xen_store_evtchn;
+
+#endif /* _XENBUS_COMMS_H */
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_dev.c linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_dev.c
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_dev.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_dev.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,404 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_dev.c linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_dev.c
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_dev.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_dev.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,408 @@
+/*
+ * xenbus_dev.c
+ *
@@ -105809,14 +174403,16 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_dev.c linux-2.6.18-xen-3.2.0
+ container_of(watch, struct watch_adapter, watch);
+ struct xsd_sockmsg hdr;
+ const char *path, *token;
-+ int path_len, tok_len, body_len;
-+
++ int path_len, tok_len, body_len, data_len = 0;
++
+ path = vec[XS_WATCH_PATH];
+ token = adap->token;
+
+ path_len = strlen(path) + 1;
+ tok_len = strlen(token) + 1;
-+ body_len = path_len + tok_len;
++ if (len > 2)
++ data_len = vec[len] - vec[2] + 1;
++ body_len = path_len + tok_len + data_len;
+
+ hdr.type = XS_WATCH_EVENT;
+ hdr.len = body_len;
@@ -105825,6 +174421,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_dev.c linux-2.6.18-xen-3.2.0
+ queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr));
+ queue_reply(adap->dev_data, (char *)path, path_len);
+ queue_reply(adap->dev_data, (char *)token, tok_len);
++ if (len > 2)
++ queue_reply(adap->dev_data, (char *)vec[2], data_len);
+ mutex_unlock(&adap->dev_data->reply_mutex);
+}
+
@@ -105918,7 +174516,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_dev.c linux-2.6.18-xen-3.2.0
+ token++;
+
+ if (msg_type == XS_WATCH) {
-+ watch = kmalloc(sizeof(*watch), GFP_KERNEL);
++ watch = kzalloc(sizeof(*watch), GFP_KERNEL);
+ watch->watch.node = kmalloc(strlen(path)+1,
+ GFP_KERNEL);
+ strcpy((char *)watch->watch.node, path);
@@ -106042,10 +174640,306 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_dev.c linux-2.6.18-xen-3.2.0
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.c linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_probe.c
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_probe.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,1150 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe_backend.c linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_probe_backend.c
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe_backend.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_probe_backend.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,292 @@
++/******************************************************************************
++ * Talks to Xen Store to figure out what devices we have (backend half).
++ *
++ * Copyright (C) 2005 Rusty Russell, IBM Corporation
++ * Copyright (C) 2005 Mike Wray, Hewlett-Packard
++ * Copyright (C) 2005, 2006 XenSource Ltd
++ * Copyright (C) 2007 Solarflare Communications, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#define DPRINTK(fmt, args...) \
++ pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \
++ __FUNCTION__, __LINE__, ##args)
++
++#include <linux/kernel.h>
++#include <linux/err.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/fcntl.h>
++#include <linux/mm.h>
++#include <linux/notifier.h>
++
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/maddr.h>
++#include <asm/pgtable.h>
++#include <asm/hypervisor.h>
++#include <xen/xenbus.h>
++#include <xen/xen_proc.h>
++#include <xen/evtchn.h>
++#include <xen/features.h>
++
++#include "xenbus_comms.h"
++#include "xenbus_probe.h"
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++static int xenbus_uevent_backend(struct device *dev, char **envp,
++ int num_envp, char *buffer, int buffer_size);
++static int xenbus_probe_backend(const char *type, const char *domid);
++
++extern int read_otherend_details(struct xenbus_device *xendev,
++ char *id_node, char *path_node);
++
++static int read_frontend_details(struct xenbus_device *xendev)
++{
++ return read_otherend_details(xendev, "frontend-id", "frontend");
++}
++
++/* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
++static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
++{
++ int domid, err;
++ const char *devid, *type, *frontend;
++ unsigned int typelen;
++
++ type = strchr(nodename, '/');
++ if (!type)
++ return -EINVAL;
++ type++;
++ typelen = strcspn(type, "/");
++ if (!typelen || type[typelen] != '/')
++ return -EINVAL;
++
++ devid = strrchr(nodename, '/') + 1;
++
++ err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid,
++ "frontend", NULL, &frontend,
++ NULL);
++ if (err)
++ return err;
++ if (strlen(frontend) == 0)
++ err = -ERANGE;
++ if (!err && !xenbus_exists(XBT_NIL, frontend, ""))
++ err = -ENOENT;
++ kfree(frontend);
++
++ if (err)
++ return err;
++
++ if (snprintf(bus_id, BUS_ID_SIZE,
++ "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE)
++ return -ENOSPC;
++ return 0;
++}
++
++static struct xen_bus_type xenbus_backend = {
++ .root = "backend",
++ .levels = 3, /* backend/type/<frontend>/<id> */
++ .get_bus_id = backend_bus_id,
++ .probe = xenbus_probe_backend,
++ .error = -ENODEV,
++ .bus = {
++ .name = "xen-backend",
++ .match = xenbus_match,
++ .probe = xenbus_dev_probe,
++ .remove = xenbus_dev_remove,
++// .shutdown = xenbus_dev_shutdown,
++ .uevent = xenbus_uevent_backend,
++ },
++ .dev = {
++ .bus_id = "xen-backend",
++ },
++};
++
++static int xenbus_uevent_backend(struct device *dev, char **envp,
++ int num_envp, char *buffer, int buffer_size)
++{
++ struct xenbus_device *xdev;
++ struct xenbus_driver *drv;
++ int i = 0;
++ int length = 0;
++
++ DPRINTK("");
++
++ if (dev == NULL)
++ return -ENODEV;
++
++ xdev = to_xenbus_device(dev);
++ if (xdev == NULL)
++ return -ENODEV;
++
++ /* stuff we want to pass to /sbin/hotplug */
++ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
++ "XENBUS_TYPE=%s", xdev->devicetype);
++
++ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
++ "XENBUS_PATH=%s", xdev->nodename);
++
++ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
++ "XENBUS_BASE_PATH=%s", xenbus_backend.root);
++
++ /* terminate, set to next free slot, shrink available space */
++ envp[i] = NULL;
++ envp = &envp[i];
++ num_envp -= i;
++ buffer = &buffer[length];
++ buffer_size -= length;
++
++ if (dev->driver) {
++ drv = to_xenbus_driver(dev->driver);
++ if (drv && drv->uevent)
++ return drv->uevent(xdev, envp, num_envp, buffer,
++ buffer_size);
++ }
++
++ return 0;
++}
++
++int xenbus_register_backend(struct xenbus_driver *drv)
++{
++ drv->read_otherend_details = read_frontend_details;
++
++ return xenbus_register_driver_common(drv, &xenbus_backend);
++}
++EXPORT_SYMBOL_GPL(xenbus_register_backend);
++
++/* backend/<typename>/<frontend-uuid>/<name> */
++static int xenbus_probe_backend_unit(const char *dir,
++ const char *type,
++ const char *name)
++{
++ char *nodename;
++ int err;
++
++ nodename = kasprintf(GFP_KERNEL, "%s/%s", dir, name);
++ if (!nodename)
++ return -ENOMEM;
++
++ DPRINTK("%s\n", nodename);
++
++ err = xenbus_probe_node(&xenbus_backend, type, nodename);
++ kfree(nodename);
++ return err;
++}
++
++/* backend/<typename>/<frontend-domid> */
++static int xenbus_probe_backend(const char *type, const char *domid)
++{
++ char *nodename;
++ int err = 0;
++ char **dir;
++ unsigned int i, dir_n = 0;
++
++ DPRINTK("");
++
++ nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", xenbus_backend.root, type, domid);
++ if (!nodename)
++ return -ENOMEM;
++
++ dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n);
++ if (IS_ERR(dir)) {
++ kfree(nodename);
++ return PTR_ERR(dir);
++ }
++
++ for (i = 0; i < dir_n; i++) {
++ err = xenbus_probe_backend_unit(nodename, type, dir[i]);
++ if (err)
++ break;
++ }
++ kfree(dir);
++ kfree(nodename);
++ return err;
++}
++
++static void backend_changed(struct xenbus_watch *watch,
++ const char **vec, unsigned int len)
++{
++ DPRINTK("");
++
++ dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
++}
++
++static struct xenbus_watch be_watch = {
++ .node = "backend",
++ .callback = backend_changed,
++};
++
++void xenbus_backend_suspend(int (*fn)(struct device *, void *))
++{
++ DPRINTK("");
++ if (!xenbus_backend.error)
++ bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn);
++}
++
++void xenbus_backend_resume(int (*fn)(struct device *, void *))
++{
++ DPRINTK("");
++ if (!xenbus_backend.error)
++ bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn);
++}
++
++void xenbus_backend_probe_and_watch(void)
++{
++ xenbus_probe_devices(&xenbus_backend);
++ register_xenbus_watch(&be_watch);
++}
++
++void xenbus_backend_bus_register(void)
++{
++ xenbus_backend.error = bus_register(&xenbus_backend.bus);
++ if (xenbus_backend.error)
++ printk(KERN_WARNING
++ "XENBUS: Error registering backend bus: %i\n",
++ xenbus_backend.error);
++}
++
++void xenbus_backend_device_register(void)
++{
++ if (xenbus_backend.error)
++ return;
++
++ xenbus_backend.error = device_register(&xenbus_backend.dev);
++ if (xenbus_backend.error) {
++ bus_unregister(&xenbus_backend.bus);
++ printk(KERN_WARNING
++ "XENBUS: Error registering backend device: %i\n",
++ xenbus_backend.error);
++ }
++}
++
++int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *))
++{
++ return bus_for_each_dev(&xenbus_backend.bus, NULL, arg, fn);
++}
++EXPORT_SYMBOL_GPL(xenbus_for_each_backend);
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.c linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_probe.c
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_probe.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,1153 @@
+/******************************************************************************
+ * Talks to Xen Store to figure out what devices we have.
+ *
@@ -106395,6 +175289,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.c linux-2.6.18-xen-3.2
+
+ DPRINTK("%s", dev->nodename);
+
++ if (is_initial_xendomain())
++ return;
++
+ get_device(&dev->dev);
+ if (dev->state != XenbusStateConnected) {
+ printk("%s: %s: %s != Connected, skipping\n", __FUNCTION__,
@@ -107196,9 +176093,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.c linux-2.6.18-xen-3.2
+ return bus_for_each_dev(&xenbus_frontend.bus, NULL, arg, fn);
+}
+EXPORT_SYMBOL_GPL(xenbus_for_each_frontend);
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.h linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_probe.h
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_probe.h 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.h linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_probe.h
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_probe.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * xenbus_probe.h
@@ -107275,306 +176172,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe.h linux-2.6.18-xen-3.2
+
+#endif
+
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe_backend.c linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_probe_backend.c
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_probe_backend.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_probe_backend.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,292 @@
-+/******************************************************************************
-+ * Talks to Xen Store to figure out what devices we have (backend half).
-+ *
-+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
-+ * Copyright (C) 2005 Mike Wray, Hewlett-Packard
-+ * Copyright (C) 2005, 2006 XenSource Ltd
-+ * Copyright (C) 2007 Solarflare Communications, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License version 2
-+ * as published by the Free Software Foundation; or, when distributed
-+ * separately from the Linux kernel or incorporated into other
-+ * software packages, subject to the following license:
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this source file (the "Software"), to deal in the Software without
-+ * restriction, including without limitation the rights to use, copy, modify,
-+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
-+ * and to permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ */
-+
-+#define DPRINTK(fmt, args...) \
-+ pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \
-+ __FUNCTION__, __LINE__, ##args)
-+
-+#include <linux/kernel.h>
-+#include <linux/err.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/fcntl.h>
-+#include <linux/mm.h>
-+#include <linux/notifier.h>
-+
-+#include <asm/io.h>
-+#include <asm/page.h>
-+#include <asm/maddr.h>
-+#include <asm/pgtable.h>
-+#include <asm/hypervisor.h>
-+#include <xen/xenbus.h>
-+#include <xen/xen_proc.h>
-+#include <xen/evtchn.h>
-+#include <xen/features.h>
-+
-+#include "xenbus_comms.h"
-+#include "xenbus_probe.h"
-+
-+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
-+#include <xen/platform-compat.h>
-+#endif
-+
-+static int xenbus_uevent_backend(struct device *dev, char **envp,
-+ int num_envp, char *buffer, int buffer_size);
-+static int xenbus_probe_backend(const char *type, const char *domid);
-+
-+extern int read_otherend_details(struct xenbus_device *xendev,
-+ char *id_node, char *path_node);
-+
-+static int read_frontend_details(struct xenbus_device *xendev)
-+{
-+ return read_otherend_details(xendev, "frontend-id", "frontend");
-+}
-+
-+/* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
-+static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
-+{
-+ int domid, err;
-+ const char *devid, *type, *frontend;
-+ unsigned int typelen;
-+
-+ type = strchr(nodename, '/');
-+ if (!type)
-+ return -EINVAL;
-+ type++;
-+ typelen = strcspn(type, "/");
-+ if (!typelen || type[typelen] != '/')
-+ return -EINVAL;
-+
-+ devid = strrchr(nodename, '/') + 1;
-+
-+ err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid,
-+ "frontend", NULL, &frontend,
-+ NULL);
-+ if (err)
-+ return err;
-+ if (strlen(frontend) == 0)
-+ err = -ERANGE;
-+ if (!err && !xenbus_exists(XBT_NIL, frontend, ""))
-+ err = -ENOENT;
-+ kfree(frontend);
-+
-+ if (err)
-+ return err;
-+
-+ if (snprintf(bus_id, BUS_ID_SIZE,
-+ "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE)
-+ return -ENOSPC;
-+ return 0;
-+}
-+
-+static struct xen_bus_type xenbus_backend = {
-+ .root = "backend",
-+ .levels = 3, /* backend/type/<frontend>/<id> */
-+ .get_bus_id = backend_bus_id,
-+ .probe = xenbus_probe_backend,
-+ .error = -ENODEV,
-+ .bus = {
-+ .name = "xen-backend",
-+ .match = xenbus_match,
-+ .probe = xenbus_dev_probe,
-+ .remove = xenbus_dev_remove,
-+// .shutdown = xenbus_dev_shutdown,
-+ .uevent = xenbus_uevent_backend,
-+ },
-+ .dev = {
-+ .bus_id = "xen-backend",
-+ },
-+};
-+
-+static int xenbus_uevent_backend(struct device *dev, char **envp,
-+ int num_envp, char *buffer, int buffer_size)
-+{
-+ struct xenbus_device *xdev;
-+ struct xenbus_driver *drv;
-+ int i = 0;
-+ int length = 0;
-+
-+ DPRINTK("");
-+
-+ if (dev == NULL)
-+ return -ENODEV;
-+
-+ xdev = to_xenbus_device(dev);
-+ if (xdev == NULL)
-+ return -ENODEV;
-+
-+ /* stuff we want to pass to /sbin/hotplug */
-+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-+ "XENBUS_TYPE=%s", xdev->devicetype);
-+
-+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-+ "XENBUS_PATH=%s", xdev->nodename);
-+
-+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-+ "XENBUS_BASE_PATH=%s", xenbus_backend.root);
-+
-+ /* terminate, set to next free slot, shrink available space */
-+ envp[i] = NULL;
-+ envp = &envp[i];
-+ num_envp -= i;
-+ buffer = &buffer[length];
-+ buffer_size -= length;
-+
-+ if (dev->driver) {
-+ drv = to_xenbus_driver(dev->driver);
-+ if (drv && drv->uevent)
-+ return drv->uevent(xdev, envp, num_envp, buffer,
-+ buffer_size);
-+ }
-+
-+ return 0;
-+}
-+
-+int xenbus_register_backend(struct xenbus_driver *drv)
-+{
-+ drv->read_otherend_details = read_frontend_details;
-+
-+ return xenbus_register_driver_common(drv, &xenbus_backend);
-+}
-+EXPORT_SYMBOL_GPL(xenbus_register_backend);
-+
-+/* backend/<typename>/<frontend-uuid>/<name> */
-+static int xenbus_probe_backend_unit(const char *dir,
-+ const char *type,
-+ const char *name)
-+{
-+ char *nodename;
-+ int err;
-+
-+ nodename = kasprintf(GFP_KERNEL, "%s/%s", dir, name);
-+ if (!nodename)
-+ return -ENOMEM;
-+
-+ DPRINTK("%s\n", nodename);
-+
-+ err = xenbus_probe_node(&xenbus_backend, type, nodename);
-+ kfree(nodename);
-+ return err;
-+}
-+
-+/* backend/<typename>/<frontend-domid> */
-+static int xenbus_probe_backend(const char *type, const char *domid)
-+{
-+ char *nodename;
-+ int err = 0;
-+ char **dir;
-+ unsigned int i, dir_n = 0;
-+
-+ DPRINTK("");
-+
-+ nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", xenbus_backend.root, type, domid);
-+ if (!nodename)
-+ return -ENOMEM;
-+
-+ dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n);
-+ if (IS_ERR(dir)) {
-+ kfree(nodename);
-+ return PTR_ERR(dir);
-+ }
-+
-+ for (i = 0; i < dir_n; i++) {
-+ err = xenbus_probe_backend_unit(nodename, type, dir[i]);
-+ if (err)
-+ break;
-+ }
-+ kfree(dir);
-+ kfree(nodename);
-+ return err;
-+}
-+
-+static void backend_changed(struct xenbus_watch *watch,
-+ const char **vec, unsigned int len)
-+{
-+ DPRINTK("");
-+
-+ dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
-+}
-+
-+static struct xenbus_watch be_watch = {
-+ .node = "backend",
-+ .callback = backend_changed,
-+};
-+
-+void xenbus_backend_suspend(int (*fn)(struct device *, void *))
-+{
-+ DPRINTK("");
-+ if (!xenbus_backend.error)
-+ bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn);
-+}
-+
-+void xenbus_backend_resume(int (*fn)(struct device *, void *))
-+{
-+ DPRINTK("");
-+ if (!xenbus_backend.error)
-+ bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn);
-+}
-+
-+void xenbus_backend_probe_and_watch(void)
-+{
-+ xenbus_probe_devices(&xenbus_backend);
-+ register_xenbus_watch(&be_watch);
-+}
-+
-+void xenbus_backend_bus_register(void)
-+{
-+ xenbus_backend.error = bus_register(&xenbus_backend.bus);
-+ if (xenbus_backend.error)
-+ printk(KERN_WARNING
-+ "XENBUS: Error registering backend bus: %i\n",
-+ xenbus_backend.error);
-+}
-+
-+void xenbus_backend_device_register(void)
-+{
-+ if (xenbus_backend.error)
-+ return;
-+
-+ xenbus_backend.error = device_register(&xenbus_backend.dev);
-+ if (xenbus_backend.error) {
-+ bus_unregister(&xenbus_backend.bus);
-+ printk(KERN_WARNING
-+ "XENBUS: Error registering backend device: %i\n",
-+ xenbus_backend.error);
-+ }
-+}
-+
-+int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *))
-+{
-+ return bus_for_each_dev(&xenbus_backend.bus, NULL, arg, fn);
-+}
-+EXPORT_SYMBOL_GPL(xenbus_for_each_backend);
-diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_xs.c
---- linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenbus/xenbus_xs.c 2008-02-15 16:22:06.000000000 -0800
-@@ -0,0 +1,886 @@
+diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_xs.c
+--- linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenbus/xenbus_xs.c 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,902 @@
+/******************************************************************************
+ * xenbus_xs.c
+ *
@@ -107868,9 +176469,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+ char *buffer;
+
+ if (strlen(name) == 0)
-+ buffer = kasprintf(GFP_KERNEL|__GFP_HIGH, "%s", dir);
++ buffer = kasprintf(GFP_NOIO | __GFP_HIGH, "%s", dir);
+ else
-+ buffer = kasprintf(GFP_KERNEL|__GFP_HIGH, "%s/%s", dir, name);
++ buffer = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/%s", dir, name);
+ return (!buffer) ? ERR_PTR(-ENOMEM) : buffer;
+}
+
@@ -107879,10 +176480,10 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+ char *p, **ret;
+
+ /* Count the strings. */
-+ *num = count_strings(strings, len);
++ *num = count_strings(strings, len) + 1;
+
+ /* Transfer to one big alloc for easy freeing. */
-+ ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL|__GFP_HIGH);
++ ret = kmalloc(*num * sizeof(char *) + len, GFP_NOIO | __GFP_HIGH);
+ if (!ret) {
+ kfree(strings);
+ return ERR_PTR(-ENOMEM);
@@ -107893,6 +176494,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+ strings = (char *)&ret[*num];
+ for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
+ ret[(*num)++] = p;
++ ret[*num] = strings + len;
+
+ return ret;
+}
@@ -108083,7 +176685,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+#define PRINTF_BUFFER_SIZE 4096
+ char *printf_buffer;
+
-+ printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL|__GFP_HIGH);
++ printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_NOIO | __GFP_HIGH);
+ if (printf_buffer == NULL)
+ return -ENOMEM;
+
@@ -108206,6 +176808,8 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+ char token[sizeof(watch) * 2 + 1];
+ int err;
+
++ BUG_ON(watch->flags & XBWF_new_thread);
++
+ sprintf(token, "%lX", (long)watch);
+
+ down_read(&xs_state.watch_mutex);
@@ -108315,16 +176919,29 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+ list_del(ent);
+ spin_unlock(&watch_events_lock);
+
-+ if (ent != &watch_events) {
-+ msg = list_entry(ent, struct xs_stored_msg, list);
-+ if (msg->u.watch.handle->flags & XBWF_new_thread)
-+ kthread_run(xenwatch_handle_callback,
-+ msg, "xenwatch_cb");
-+ else
-+ xenwatch_handle_callback(msg);
++ if (ent == &watch_events) {
++ mutex_unlock(&xenwatch_mutex);
++ continue;
+ }
+
-+ mutex_unlock(&xenwatch_mutex);
++ msg = list_entry(ent, struct xs_stored_msg, list);
++
++ /*
++ * Unlock the mutex before running an XBWF_new_thread
++ * handler. kthread_run can block which can deadlock
++ * against unregister_xenbus_watch() if we need to
++ * unregister other watches in order to make
++ * progress. This can occur on resume before the swap
++ * device is attached.
++ */
++ if (msg->u.watch.handle->flags & XBWF_new_thread) {
++ mutex_unlock(&xenwatch_mutex);
++ kthread_run(xenwatch_handle_callback,
++ msg, "xenwatch_cb");
++ } else {
++ xenwatch_handle_callback(msg);
++ mutex_unlock(&xenwatch_mutex);
++ }
+ }
+
+ return 0;
@@ -108352,7 +176969,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+ }
+
+
-+ msg = kmalloc(sizeof(*msg), GFP_KERNEL|__GFP_HIGH);
++ msg = kmalloc(sizeof(*msg), GFP_NOIO | __GFP_HIGH);
+ if (msg == NULL) {
+ err = -ENOMEM;
+ goto out;
@@ -108364,7 +176981,7 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+ goto out;
+ }
+
-+ body = kmalloc(msg->hdr.len + 1, GFP_KERNEL|__GFP_HIGH);
++ body = kmalloc(msg->hdr.len + 1, GFP_NOIO | __GFP_HIGH);
+ if (body == NULL) {
+ kfree(msg);
+ err = -ENOMEM;
@@ -108461,9 +177078,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenbus/xenbus_xs.c linux-2.6.18-xen-3.2.0/
+
+ return 0;
+}
-diff -rpuN linux-2.6.18.8/drivers/xen/xenoprof/xenoprofile.c linux-2.6.18-xen-3.2.0/drivers/xen/xenoprof/xenoprofile.c
---- linux-2.6.18.8/drivers/xen/xenoprof/xenoprofile.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/drivers/xen/xenoprof/xenoprofile.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/drivers/xen/xenoprof/xenoprofile.c linux-2.6.18-xen-3.3.0/drivers/xen/xenoprof/xenoprofile.c
+--- linux-2.6.18.8/drivers/xen/xenoprof/xenoprofile.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/drivers/xen/xenoprof/xenoprofile.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,546 @@
+/**
+ * @file xenoprofile.c
@@ -109011,32 +177628,9 @@ diff -rpuN linux-2.6.18.8/drivers/xen/xenoprof/xenoprofile.c linux-2.6.18-xen-3.
+ WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL));
+ }
+}
-diff -rpuN linux-2.6.18.8/fs/Kconfig linux-2.6.18-xen-3.2.0/fs/Kconfig
---- linux-2.6.18.8/fs/Kconfig 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/Kconfig 2008-02-15 16:22:06.000000000 -0800
-@@ -826,6 +826,11 @@ config PROC_VMCORE
- help
- Exports the dump image of crashed kernel in ELF format.
-
-+config PROC_IOMEM_MACHINE
-+ bool
-+ depends on PROC_FS && EXPERIMENTAL && KEXEC && XEN && IA64
-+ default y
-+
- config SYSFS
- bool "sysfs file system support" if EMBEDDED
- default y
-@@ -865,6 +870,7 @@ config TMPFS
- config HUGETLBFS
- bool "HugeTLB file system support"
- depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
-+ depends on !XEN
- help
- hugetlbfs is a filesystem backing for HugeTLB pages, based on
- ramfs. For architectures that support it, say Y here and read
-diff -rpuN linux-2.6.18.8/fs/aio.c linux-2.6.18-xen-3.2.0/fs/aio.c
---- linux-2.6.18.8/fs/aio.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/aio.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/aio.c linux-2.6.18-xen-3.3.0/fs/aio.c
+--- linux-2.6.18.8/fs/aio.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/aio.c 2008-08-21 11:36:07.000000000 +0200
@@ -34,6 +34,11 @@
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -109220,9 +177814,23 @@ diff -rpuN linux-2.6.18.8/fs/aio.c linux-2.6.18-xen-3.2.0/fs/aio.c
get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
io_destroy(ioctx);
-diff -rpuN linux-2.6.18.8/fs/bio.c linux-2.6.18-xen-3.2.0/fs/bio.c
---- linux-2.6.18.8/fs/bio.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/bio.c 2008-02-15 16:22:06.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/binfmt_elf.c linux-2.6.18-xen-3.3.0/fs/binfmt_elf.c
+--- linux-2.6.18.8/fs/binfmt_elf.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/binfmt_elf.c 2008-08-21 11:36:07.000000000 +0200
+@@ -1170,6 +1170,10 @@ static int dump_seek(struct file *file,
+ */
+ static int maydump(struct vm_area_struct *vma)
+ {
++ /* The vma can be set up to tell us the answer directly. */
++ if (vma->vm_flags & VM_ALWAYSDUMP)
++ return 1;
++
+ /* Do not dump I/O mapped devices or special mappings */
+ if (vma->vm_flags & (VM_IO | VM_RESERVED))
+ return 0;
+diff -rpuN linux-2.6.18.8/fs/bio.c linux-2.6.18-xen-3.3.0/fs/bio.c
+--- linux-2.6.18.8/fs/bio.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/bio.c 2008-08-21 11:36:07.000000000 +0200
@@ -112,7 +112,8 @@ void bio_free(struct bio *bio, struct bi
BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
@@ -109233,22 +177841,24 @@ diff -rpuN linux-2.6.18.8/fs/bio.c linux-2.6.18-xen-3.2.0/fs/bio.c
mempool_free(bio, bio_set->bio_pool);
}
-diff -rpuN linux-2.6.18.8/fs/compat_ioctl.c linux-2.6.18-xen-3.2.0/fs/compat_ioctl.c
---- linux-2.6.18.8/fs/compat_ioctl.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/compat_ioctl.c 2008-02-15 16:22:07.000000000 -0800
-@@ -124,6 +124,11 @@
+diff -rpuN linux-2.6.18.8/fs/compat_ioctl.c linux-2.6.18-xen-3.3.0/fs/compat_ioctl.c
+--- linux-2.6.18.8/fs/compat_ioctl.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/compat_ioctl.c 2008-08-21 11:36:07.000000000 +0200
+@@ -124,6 +124,13 @@
#include <linux/dvb/video.h>
#include <linux/lp.h>
++#ifdef CONFIG_XEN
+#include <xen/interface/xen.h>
+#include <xen/public/evtchn.h>
+#include <xen/public/privcmd.h>
+#include <xen/compat_ioctl.h>
++#endif
+
/* Aiee. Someone does not find a difference between int and long */
#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int)
#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int)
-@@ -2948,6 +2953,18 @@ COMPATIBLE_IOCTL(LPRESET)
+@@ -2948,6 +2955,18 @@ COMPATIBLE_IOCTL(LPRESET)
/*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/
COMPATIBLE_IOCTL(LPGETFLAGS)
HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans)
@@ -109267,9 +177877,64 @@ diff -rpuN linux-2.6.18.8/fs/compat_ioctl.c linux-2.6.18-xen-3.2.0/fs/compat_ioc
};
int ioctl_table_size = ARRAY_SIZE(ioctl_start);
-diff -rpuN linux-2.6.18.8/fs/eventpoll.c linux-2.6.18-xen-3.2.0/fs/eventpoll.c
---- linux-2.6.18.8/fs/eventpoll.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/eventpoll.c 2008-02-15 16:22:07.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/debugfs/file.c linux-2.6.18-xen-3.3.0/fs/debugfs/file.c
+--- linux-2.6.18.8/fs/debugfs/file.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/debugfs/file.c 2008-08-21 11:36:07.000000000 +0200
+@@ -170,6 +170,51 @@ struct dentry *debugfs_create_u32(const
+ }
+ EXPORT_SYMBOL_GPL(debugfs_create_u32);
+
++
++static void debugfs_u64_set(void *data, u64 val)
++{
++ *(u64 *)data = val;
++}
++
++static u64 debugfs_u64_get(void *data)
++{
++ return *(u64 *)data;
++}
++DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n");
++
++/**
++ * debugfs_create_u64 - create a file in the debugfs filesystem that is used to read and write an unsigned 64 bit value.
++ *
++ * @name: a pointer to a string containing the name of the file to create.
++ * @mode: the permission that the file should have
++ * @parent: a pointer to the parent dentry for this file. This should be a
++ * directory dentry if set. If this paramater is NULL, then the
++ * file will be created in the root of the debugfs filesystem.
++ * @value: a pointer to the variable that the file should read to and write
++ * from.
++ *
++ * This function creates a file in debugfs with the given name that
++ * contains the value of the variable @value. If the @mode variable is so
++ * set, it can be read from, and written to.
++ *
++ * This function will return a pointer to a dentry if it succeeds. This
++ * pointer must be passed to the debugfs_remove() function when the file is
++ * to be removed (no automatic cleanup happens if your module is unloaded,
++ * you are responsible here.) If an error occurs, NULL will be returned.
++ *
++ * If debugfs is not enabled in the kernel, the value -ENODEV will be
++ * returned. It is not wise to check for this value, but rather, check for
++ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
++ * code.
++ */
++struct dentry *debugfs_create_u64(const char *name, mode_t mode,
++ struct dentry *parent, u64 *value)
++{
++ return debugfs_create_file(name, mode, parent, value, &fops_u64);
++}
++EXPORT_SYMBOL_GPL(debugfs_create_u64);
++
++
+ static ssize_t read_file_bool(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+ {
+diff -rpuN linux-2.6.18.8/fs/eventpoll.c linux-2.6.18-xen-3.3.0/fs/eventpoll.c
+--- linux-2.6.18.8/fs/eventpoll.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/eventpoll.c 2008-08-21 11:36:07.000000000 +0200
@@ -236,8 +236,6 @@ struct ep_pqueue {
static void ep_poll_safewake_init(struct poll_safewake *psw);
@@ -109344,9 +178009,32 @@ diff -rpuN linux-2.6.18.8/fs/eventpoll.c linux-2.6.18-xen-3.2.0/fs/eventpoll.c
/*
* Mark the inode dirty from the very beginning,
-diff -rpuN linux-2.6.18.8/fs/lockd/svc.c linux-2.6.18-xen-3.2.0/fs/lockd/svc.c
---- linux-2.6.18.8/fs/lockd/svc.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/lockd/svc.c 2008-02-15 16:22:08.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/Kconfig linux-2.6.18-xen-3.3.0/fs/Kconfig
+--- linux-2.6.18.8/fs/Kconfig 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/Kconfig 2008-08-21 11:36:07.000000000 +0200
+@@ -826,6 +826,11 @@ config PROC_VMCORE
+ help
+ Exports the dump image of crashed kernel in ELF format.
+
++config PROC_IOMEM_MACHINE
++ bool
++ depends on PROC_FS && EXPERIMENTAL && KEXEC && XEN && IA64
++ default y
++
+ config SYSFS
+ bool "sysfs file system support" if EMBEDDED
+ default y
+@@ -865,6 +870,7 @@ config TMPFS
+ config HUGETLBFS
+ bool "HugeTLB file system support"
+ depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
++ depends on !XEN
+ help
+ hugetlbfs is a filesystem backing for HugeTLB pages, based on
+ ramfs. For architectures that support it, say Y here and read
+diff -rpuN linux-2.6.18.8/fs/lockd/svc.c linux-2.6.18-xen-3.3.0/fs/lockd/svc.c
+--- linux-2.6.18.8/fs/lockd/svc.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/lockd/svc.c 2008-08-21 11:36:07.000000000 +0200
@@ -323,9 +323,6 @@ EXPORT_SYMBOL(lockd_down);
* Sysctl parameters (same as module parameters, different interface).
*/
@@ -109357,9 +178045,9 @@ diff -rpuN linux-2.6.18.8/fs/lockd/svc.c linux-2.6.18-xen-3.2.0/fs/lockd/svc.c
static ctl_table nlm_sysctls[] = {
{
.ctl_name = CTL_UNNUMBERED,
-diff -rpuN linux-2.6.18.8/fs/nfs/sysctl.c linux-2.6.18-xen-3.2.0/fs/nfs/sysctl.c
---- linux-2.6.18.8/fs/nfs/sysctl.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/nfs/sysctl.c 2008-02-15 16:22:08.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/nfs/sysctl.c linux-2.6.18-xen-3.3.0/fs/nfs/sysctl.c
+--- linux-2.6.18.8/fs/nfs/sysctl.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/nfs/sysctl.c 2008-08-21 11:36:07.000000000 +0200
@@ -18,11 +18,6 @@
static const int nfs_set_port_min = 0;
static const int nfs_set_port_max = 65535;
@@ -109372,9 +178060,9 @@ diff -rpuN linux-2.6.18.8/fs/nfs/sysctl.c linux-2.6.18-xen-3.2.0/fs/nfs/sysctl.c
static ctl_table nfs_cb_sysctls[] = {
#ifdef CONFIG_NFS_V4
-diff -rpuN linux-2.6.18.8/fs/proc/proc_misc.c linux-2.6.18-xen-3.2.0/fs/proc/proc_misc.c
---- linux-2.6.18.8/fs/proc/proc_misc.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/proc/proc_misc.c 2008-02-15 16:22:08.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/proc/proc_misc.c linux-2.6.18-xen-3.3.0/fs/proc/proc_misc.c
+--- linux-2.6.18.8/fs/proc/proc_misc.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/proc/proc_misc.c 2008-08-21 11:36:07.000000000 +0200
@@ -471,7 +471,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),
@@ -109384,9 +178072,9 @@ diff -rpuN linux-2.6.18.8/fs/proc/proc_misc.c linux-2.6.18-xen-3.2.0/fs/proc/pro
/* Copy values here to work around gcc-2.95.3, gcc-2.96 */
user = kstat_cpu(i).cpustat.user;
-diff -rpuN linux-2.6.18.8/fs/proc/vmcore.c linux-2.6.18-xen-3.2.0/fs/proc/vmcore.c
---- linux-2.6.18.8/fs/proc/vmcore.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/proc/vmcore.c 2008-02-15 16:22:08.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/proc/vmcore.c linux-2.6.18-xen-3.3.0/fs/proc/vmcore.c
+--- linux-2.6.18.8/fs/proc/vmcore.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/proc/vmcore.c 2008-08-21 11:36:07.000000000 +0200
@@ -514,7 +514,7 @@ static int __init parse_crash_elf64_head
/* Do some basic Verification. */
if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
@@ -109396,9 +178084,9 @@ diff -rpuN linux-2.6.18.8/fs/proc/vmcore.c linux-2.6.18-xen-3.2.0/fs/proc/vmcore
ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
ehdr.e_version != EV_CURRENT ||
-diff -rpuN linux-2.6.18.8/fs/splice.c linux-2.6.18-xen-3.2.0/fs/splice.c
---- linux-2.6.18.8/fs/splice.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/splice.c 2008-02-15 16:22:09.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/splice.c linux-2.6.18-xen-3.3.0/fs/splice.c
+--- linux-2.6.18.8/fs/splice.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/splice.c 2008-08-21 11:36:07.000000000 +0200
@@ -1141,6 +1141,9 @@ static int get_iovec_page_array(const st
if (unlikely(!base))
break;
@@ -109409,9 +178097,9 @@ diff -rpuN linux-2.6.18.8/fs/splice.c linux-2.6.18-xen-3.2.0/fs/splice.c
/*
* Get this base offset and number of pages, then map
* in the user pages.
-diff -rpuN linux-2.6.18.8/fs/xfs/linux-2.6/xfs_buf.c linux-2.6.18-xen-3.2.0/fs/xfs/linux-2.6/xfs_buf.c
---- linux-2.6.18.8/fs/xfs/linux-2.6/xfs_buf.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/fs/xfs/linux-2.6/xfs_buf.c 2008-02-15 16:22:09.000000000 -0800
+diff -rpuN linux-2.6.18.8/fs/xfs/linux-2.6/xfs_buf.c linux-2.6.18-xen-3.3.0/fs/xfs/linux-2.6/xfs_buf.c
+--- linux-2.6.18.8/fs/xfs/linux-2.6/xfs_buf.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/fs/xfs/linux-2.6/xfs_buf.c 2008-08-21 11:36:07.000000000 +0200
@@ -182,6 +182,19 @@ free_address(
{
a_list_t *aentry;
@@ -109432,9 +178120,207 @@ diff -rpuN linux-2.6.18.8/fs/xfs/linux-2.6/xfs_buf.c linux-2.6.18-xen-3.2.0/fs/x
aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
if (likely(aentry)) {
spin_lock(&as_lock);
-diff -rpuN linux-2.6.18.8/include/asm-generic/pci.h linux-2.6.18-xen-3.2.0/include/asm-generic/pci.h
---- linux-2.6.18.8/include/asm-generic/pci.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-generic/pci.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/.hg_archival.txt linux-2.6.18-xen-3.3.0/.hg_archival.txt
+--- linux-2.6.18.8/.hg_archival.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/.hg_archival.txt 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2 @@
++repo: 831230e53067cb45d27b07d037b2e907b663c2db
++node: e86b8e0ac6fdc3144976c4ea0bd922532a1fe8b4
+diff -rpuN linux-2.6.18.8/.hgignore linux-2.6.18-xen-3.3.0/.hgignore
+--- linux-2.6.18.8/.hgignore 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/.hgignore 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,3 @@
++.*\.orig$
++.*\.rej$
++\.valid-src$
+\ No newline at end of file
+diff -rpuN linux-2.6.18.8/.hgtags linux-2.6.18-xen-3.3.0/.hgtags
+--- linux-2.6.18.8/.hgtags 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/.hgtags 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,2 @@
++831230e53067cb45d27b07d037b2e907b663c2db v2.6.18
++08e85e79c65d0316bfda5e77e8a0dc7ab9ca181a xen-3.2.0
+diff -rpuN linux-2.6.18.8/include/acpi/aclocal.h linux-2.6.18-xen-3.3.0/include/acpi/aclocal.h
+--- linux-2.6.18.8/include/acpi/aclocal.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/acpi/aclocal.h 2008-08-21 11:36:07.000000000 +0200
+@@ -708,7 +708,7 @@ struct acpi_bit_register_info {
+ * must be preserved.
+ */
+ #define ACPI_PM1_STATUS_PRESERVED_BITS 0x0800 /* Bit 11 */
+-#define ACPI_PM1_CONTROL_PRESERVED_BITS 0x0201 /* Bit 9, Bit 0 (SCI_EN) */
++#define ACPI_PM1_CONTROL_PRESERVED_BITS 0x0200 /* Bit 9 (whatever) */
+
+ /*
+ * Register IDs
+diff -rpuN linux-2.6.18.8/include/acpi/pdc_intel.h linux-2.6.18-xen-3.3.0/include/acpi/pdc_intel.h
+--- linux-2.6.18.8/include/acpi/pdc_intel.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/acpi/pdc_intel.h 2008-08-21 11:36:07.000000000 +0200
+@@ -13,6 +13,7 @@
+ #define ACPI_PDC_SMP_C_SWCOORD (0x0040)
+ #define ACPI_PDC_SMP_T_SWCOORD (0x0080)
+ #define ACPI_PDC_C_C1_FFH (0x0100)
++#define ACPI_PDC_C_C2C3_FFH (0x0200)
+
+ #define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
+ ACPI_PDC_C_C1_HALT | \
+@@ -25,6 +26,8 @@
+
+ #define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
+ ACPI_PDC_SMP_C1PT | \
+- ACPI_PDC_C_C1_HALT)
++ ACPI_PDC_C_C1_HALT | \
++ ACPI_PDC_C_C1_FFH | \
++ ACPI_PDC_C_C2C3_FFH)
+
+ #endif /* __PDC_INTEL_H__ */
+diff -rpuN linux-2.6.18.8/include/acpi/processor.h linux-2.6.18-xen-3.3.0/include/acpi/processor.h
+--- linux-2.6.18.8/include/acpi/processor.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/acpi/processor.h 2008-08-21 11:36:07.000000000 +0200
+@@ -21,6 +21,12 @@
+ #define ACPI_PSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */
+ #define ACPI_PSD_REV0_ENTRIES 5
+
++#ifdef CONFIG_XEN
++#define NR_ACPI_CPUS (NR_CPUS < 256 ? 256 : NR_CPUS)
++#else
++#define NR_ACPI_CPUS NR_CPUS
++#endif /* CONFIG_XEN */
++
+ /*
+ * Types of coordination defined in ACPI 3.0. Same macros can be used across
+ * P, C and T states
+@@ -33,6 +39,17 @@
+
+ struct acpi_processor_cx;
+
++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++struct acpi_csd_package {
++ acpi_integer num_entries;
++ acpi_integer revision;
++ acpi_integer domain;
++ acpi_integer coord_type;
++ acpi_integer num_processors;
++ acpi_integer index;
++} __attribute__ ((packed));
++#endif
++
+ struct acpi_power_register {
+ u8 descriptor;
+ u16 length;
+@@ -63,6 +80,12 @@ struct acpi_processor_cx {
+ u32 power;
+ u32 usage;
+ u64 time;
++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++ /* Require raw information for external control logic */
++ struct acpi_power_register reg;
++ u32 csd_count;
++ struct acpi_csd_package *domain_info;
++#endif
+ struct acpi_processor_cx_policy promotion;
+ struct acpi_processor_cx_policy demotion;
+ };
+@@ -231,6 +254,9 @@ static inline void acpi_processor_ppc_ex
+ {
+ return;
+ }
++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++int acpi_processor_ppc_has_changed(struct acpi_processor *pr);
++#else
+ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
+ {
+ static unsigned int printout = 1;
+@@ -243,6 +269,7 @@ static inline int acpi_processor_ppc_has
+ }
+ return 0;
+ }
++#endif /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
+ #endif /* CONFIG_CPU_FREQ */
+
+ /* in processor_throttling.c */
+@@ -275,4 +302,79 @@ static inline void acpi_thermal_cpufreq_
+ }
+ #endif
+
++/*
++ * Following are interfaces geared to external processor PM control
++ * logic like a VMM
++ */
++/* Events notified to external control logic */
++#define PROCESSOR_PM_INIT 1
++#define PROCESSOR_PM_CHANGE 2
++#define PROCESSOR_HOTPLUG 3
++
++/* Objects for the PM events */
++#define PM_TYPE_IDLE 0
++#define PM_TYPE_PERF 1
++#define PM_TYPE_THR 2
++#define PM_TYPE_MAX 3
++
++/* Processor hotplug events */
++#define HOTPLUG_TYPE_ADD 0
++#define HOTPLUG_TYPE_REMOVE 1
++
++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++struct processor_extcntl_ops {
++ /* Transfer processor PM events to external control logic */
++ int (*pm_ops[PM_TYPE_MAX])(struct acpi_processor *pr, int event);
++ /* Notify physical processor status to external control logic */
++ int (*hotplug)(struct acpi_processor *pr, int event);
++};
++extern const struct processor_extcntl_ops *processor_extcntl_ops;
++
++static inline int processor_cntl_external(void)
++{
++ return (processor_extcntl_ops != NULL);
++}
++
++static inline int processor_pm_external(void)
++{
++ return processor_cntl_external() &&
++ (processor_extcntl_ops->pm_ops[PM_TYPE_IDLE] != NULL);
++}
++
++static inline int processor_pmperf_external(void)
++{
++ return processor_cntl_external() &&
++ (processor_extcntl_ops->pm_ops[PM_TYPE_PERF] != NULL);
++}
++
++static inline int processor_pmthr_external(void)
++{
++ return processor_cntl_external() &&
++ (processor_extcntl_ops->pm_ops[PM_TYPE_THR] != NULL);
++}
++
++extern int processor_notify_external(struct acpi_processor *pr,
++ int event, int type);
++extern void processor_extcntl_init(void);
++extern int processor_extcntl_prepare(struct acpi_processor *pr);
++extern int acpi_processor_get_performance_info(struct acpi_processor *pr);
++extern int acpi_processor_get_psd(struct acpi_processor *pr);
++void arch_acpi_processor_init_extcntl(const struct processor_extcntl_ops **);
++#else
++static inline int processor_cntl_external(void) {return 0;}
++static inline int processor_pm_external(void) {return 0;}
++static inline int processor_pmperf_external(void) {return 0;}
++static inline int processor_pmthr_external(void) {return 0;}
++static inline int processor_notify_external(struct acpi_processor *pr,
++ int event, int type)
++{
++ return 0;
++}
++static inline void processor_extcntl_init(void) {}
++static inline int processor_extcntl_prepare(struct acpi_processor *pr)
++{
++ return 0;
++}
++#endif /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
++
+ #endif
+diff -rpuN linux-2.6.18.8/include/asm-generic/pci.h linux-2.6.18-xen-3.3.0/include/asm-generic/pci.h
+--- linux-2.6.18.8/include/asm-generic/pci.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-generic/pci.h 2008-08-21 11:36:07.000000000 +0200
@@ -43,7 +43,9 @@ pcibios_select_root(struct pci_dev *pdev
return root;
}
@@ -109445,9 +178331,9 @@ diff -rpuN linux-2.6.18.8/include/asm-generic/pci.h linux-2.6.18-xen-3.2.0/inclu
#ifndef HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
-diff -rpuN linux-2.6.18.8/include/asm-generic/pgtable.h linux-2.6.18-xen-3.2.0/include/asm-generic/pgtable.h
---- linux-2.6.18.8/include/asm-generic/pgtable.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-generic/pgtable.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-generic/pgtable.h linux-2.6.18-xen-3.3.0/include/asm-generic/pgtable.h
+--- linux-2.6.18.8/include/asm-generic/pgtable.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-generic/pgtable.h 2008-08-21 11:36:07.000000000 +0200
@@ -188,6 +188,10 @@ static inline void ptep_set_wrprotect(st
})
#endif
@@ -109459,9 +178345,9 @@ diff -rpuN linux-2.6.18.8/include/asm-generic/pgtable.h linux-2.6.18-xen-3.2.0/i
#ifndef __ASSEMBLY__
/*
* When walking page tables, we usually want to skip any p?d_none entries;
-diff -rpuN linux-2.6.18.8/include/asm-generic/vmlinux.lds.h linux-2.6.18-xen-3.2.0/include/asm-generic/vmlinux.lds.h
---- linux-2.6.18.8/include/asm-generic/vmlinux.lds.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-generic/vmlinux.lds.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-generic/vmlinux.lds.h linux-2.6.18-xen-3.3.0/include/asm-generic/vmlinux.lds.h
+--- linux-2.6.18.8/include/asm-generic/vmlinux.lds.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-generic/vmlinux.lds.h 2008-08-21 11:36:07.000000000 +0200
@@ -194,3 +194,6 @@
.stab.index 0 : { *(.stab.index) } \
.stab.indexstr 0 : { *(.stab.indexstr) } \
@@ -109469,18 +178355,48 @@ diff -rpuN linux-2.6.18.8/include/asm-generic/vmlinux.lds.h linux-2.6.18-xen-3.2
+
+#define NOTES \
+ .notes : { *(.note.*) } :note
-diff -rpuN linux-2.6.18.8/include/asm-i386/acpi.h linux-2.6.18-xen-3.2.0/include/asm-i386/acpi.h
---- linux-2.6.18.8/include/asm-i386/acpi.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/acpi.h 2008-02-15 16:22:10.000000000 -0800
-@@ -177,11 +177,17 @@ extern unsigned long acpi_wakeup_address
- /* early initialization routine */
- extern void acpi_reserve_bootmem(void);
+diff -rpuN linux-2.6.18.8/include/asm-i386/acpi.h linux-2.6.18-xen-3.3.0/include/asm-i386/acpi.h
+--- linux-2.6.18.8/include/asm-i386/acpi.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/acpi.h 2008-08-21 11:36:07.000000000 +0200
+@@ -31,6 +31,9 @@
+ #include <acpi/pdc_intel.h>
-+#ifdef CONFIG_ACPI_PV_SLEEP
-+extern int acpi_notify_hypervisor_state(u8 sleep_state,
-+ u32 pm1a_cnt, u32 pm1b_cnt);
-+#endif /* CONFIG_ACPI_PV_SLEEP */
- #endif /*CONFIG_ACPI_SLEEP*/
+ #include <asm/system.h> /* defines cmpxchg */
++#ifdef CONFIG_XEN
++#include <xen/interface/platform.h>
++#endif
+
+ #define COMPILER_DEPENDENT_INT64 long long
+ #define COMPILER_DEPENDENT_UINT64 unsigned long long
+@@ -156,6 +159,27 @@ static inline void acpi_disable_pci(void
+ }
+ extern int acpi_irq_balance_set(char *str);
+
++#ifdef CONFIG_XEN
++static inline int acpi_notify_hypervisor_state(u8 sleep_state,
++ u32 pm1a_cnt_val,
++ u32 pm1b_cnt_val)
++{
++ struct xen_platform_op op = {
++ .cmd = XENPF_enter_acpi_sleep,
++ .interface_version = XENPF_INTERFACE_VERSION,
++ .u = {
++ .enter_acpi_sleep = {
++ .pm1a_cnt_val = pm1a_cnt_val,
++ .pm1b_cnt_val = pm1b_cnt_val,
++ .sleep_state = sleep_state,
++ },
++ },
++ };
++
++ return HYPERVISOR_platform_op(&op);
++}
++#endif /* CONFIG_XEN */
++
+ #else /* !CONFIG_ACPI */
+
+ #define acpi_lapic 0
+@@ -181,7 +205,9 @@ extern void acpi_reserve_bootmem(void);
extern u8 x86_acpiid_to_apicid[];
@@ -109490,9 +178406,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/acpi.h linux-2.6.18-xen-3.2.0/include
#endif /*__KERNEL__*/
-diff -rpuN linux-2.6.18.8/include/asm-i386/agp.h linux-2.6.18-xen-3.2.0/include/asm-i386/agp.h
---- linux-2.6.18.8/include/asm-i386/agp.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/agp.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/agp.h linux-2.6.18-xen-3.3.0/include/asm-i386/agp.h
+--- linux-2.6.18.8/include/asm-i386/agp.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/agp.h 2008-08-21 11:36:07.000000000 +0200
@@ -12,8 +12,10 @@
* data corruption on some CPUs.
*/
@@ -109506,9 +178422,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/agp.h linux-2.6.18-xen-3.2.0/include/
#define flush_agp_mappings() global_flush_tlb()
/* Could use CLFLUSH here if the cpu supports it. But then it would
-diff -rpuN linux-2.6.18.8/include/asm-i386/apic.h linux-2.6.18-xen-3.2.0/include/asm-i386/apic.h
---- linux-2.6.18.8/include/asm-i386/apic.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/apic.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/apic.h linux-2.6.18-xen-3.3.0/include/asm-i386/apic.h
+--- linux-2.6.18.8/include/asm-i386/apic.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/apic.h 2008-08-21 11:36:07.000000000 +0200
@@ -119,10 +119,12 @@ extern void enable_NMI_through_LVT0 (voi
extern int disable_timer_pin_1;
@@ -109522,9 +178438,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/apic.h linux-2.6.18-xen-3.2.0/include
extern int timer_over_8254;
-diff -rpuN linux-2.6.18.8/include/asm-i386/e820.h linux-2.6.18-xen-3.2.0/include/asm-i386/e820.h
---- linux-2.6.18.8/include/asm-i386/e820.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/e820.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/e820.h linux-2.6.18-xen-3.3.0/include/asm-i386/e820.h
+--- linux-2.6.18.8/include/asm-i386/e820.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/e820.h 2008-08-21 11:36:07.000000000 +0200
@@ -38,6 +38,7 @@ extern struct e820map e820;
extern int e820_all_mapped(unsigned long start, unsigned long end,
@@ -109533,9 +178449,63 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/e820.h linux-2.6.18-xen-3.2.0/include
#endif/*!__ASSEMBLY__*/
-diff -rpuN linux-2.6.18.8/include/asm-i386/fixmap.h linux-2.6.18-xen-3.2.0/include/asm-i386/fixmap.h
---- linux-2.6.18.8/include/asm-i386/fixmap.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/fixmap.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/elf.h linux-2.6.18-xen-3.3.0/include/asm-i386/elf.h
+--- linux-2.6.18.8/include/asm-i386/elf.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/elf.h 2008-08-21 11:36:07.000000000 +0200
+@@ -169,50 +169,6 @@ do if (vdso_enabled) { \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE); \
+ } while (0)
+
+-/*
+- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+- * extra segments containing the vsyscall DSO contents. Dumping its
+- * contents makes post-mortem fully interpretable later without matching up
+- * the same kernel and hardware config to see what PC values meant.
+- * Dumping its extra ELF program headers includes all the other information
+- * a debugger needs to easily find how the vsyscall DSO was being used.
+- */
+-#define ELF_CORE_EXTRA_PHDRS (VDSO_HIGH_EHDR->e_phnum)
+-#define ELF_CORE_WRITE_EXTRA_PHDRS \
+-do { \
+- const struct elf_phdr *const vsyscall_phdrs = \
+- (const struct elf_phdr *) (VDSO_HIGH_BASE \
+- + VDSO_HIGH_EHDR->e_phoff); \
+- int i; \
+- Elf32_Off ofs = 0; \
+- for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) { \
+- struct elf_phdr phdr = vsyscall_phdrs[i]; \
+- if (phdr.p_type == PT_LOAD) { \
+- BUG_ON(ofs != 0); \
+- ofs = phdr.p_offset = offset; \
+- phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
+- phdr.p_filesz = phdr.p_memsz; \
+- offset += phdr.p_filesz; \
+- } \
+- else \
+- phdr.p_offset += ofs; \
+- phdr.p_paddr = 0; /* match other core phdrs */ \
+- DUMP_WRITE(&phdr, sizeof(phdr)); \
+- } \
+-} while (0)
+-#define ELF_CORE_WRITE_EXTRA_DATA \
+-do { \
+- const struct elf_phdr *const vsyscall_phdrs = \
+- (const struct elf_phdr *) (VDSO_HIGH_BASE \
+- + VDSO_HIGH_EHDR->e_phoff); \
+- int i; \
+- for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) { \
+- if (vsyscall_phdrs[i].p_type == PT_LOAD) \
+- DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \
+- PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+- } \
+-} while (0)
+-
+ #endif
+
+ #endif
+diff -rpuN linux-2.6.18.8/include/asm-i386/fixmap.h linux-2.6.18-xen-3.3.0/include/asm-i386/fixmap.h
+--- linux-2.6.18.8/include/asm-i386/fixmap.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/fixmap.h 2008-08-21 11:36:07.000000000 +0200
@@ -19,7 +19,7 @@
* Leave one empty page between vmalloc'ed areas and
* the start of the fixmap.
@@ -109554,9 +178524,21 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/fixmap.h linux-2.6.18-xen-3.2.0/inclu
#define set_fixmap(idx, phys) \
__set_fixmap(idx, phys, PAGE_KERNEL)
/*
-diff -rpuN linux-2.6.18.8/include/asm-i386/kexec.h linux-2.6.18-xen-3.2.0/include/asm-i386/kexec.h
---- linux-2.6.18.8/include/asm-i386/kexec.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/kexec.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/io_apic.h linux-2.6.18-xen-3.3.0/include/asm-i386/io_apic.h
+--- linux-2.6.18.8/include/asm-i386/io_apic.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/io_apic.h 2008-08-21 11:36:07.000000000 +0200
+@@ -12,7 +12,7 @@
+
+ #ifdef CONFIG_X86_IO_APIC
+
+-#ifdef CONFIG_PCI_MSI
++#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+ static inline int use_pci_vector(void) {return 1;}
+ static inline void disable_edge_ioapic_vector(unsigned int vector) { }
+ static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
+diff -rpuN linux-2.6.18.8/include/asm-i386/kexec.h linux-2.6.18-xen-3.3.0/include/asm-i386/kexec.h
+--- linux-2.6.18.8/include/asm-i386/kexec.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/kexec.h 2008-08-21 11:36:07.000000000 +0200
@@ -1,6 +1,26 @@
#ifndef _I386_KEXEC_H
#define _I386_KEXEC_H
@@ -109621,9 +178603,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/kexec.h linux-2.6.18-xen-3.2.0/includ
+#endif /* __ASSEMBLY__ */
#endif /* _I386_KEXEC_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-default/mach_traps.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-default/mach_traps.h
---- linux-2.6.18.8/include/asm-i386/mach-default/mach_traps.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-default/mach_traps.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-default/mach_traps.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-default/mach_traps.h
+--- linux-2.6.18.8/include/asm-i386/mach-default/mach_traps.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-default/mach_traps.h 2008-08-21 11:36:07.000000000 +0200
@@ -15,6 +15,18 @@ static inline void clear_mem_error(unsig
outb(reason, 0x61);
}
@@ -109643,9 +178625,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-default/mach_traps.h linux-2.6.1
static inline unsigned char get_nmi_reason(void)
{
return inb(0x61);
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/agp.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/agp.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/agp.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/agp.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/agp.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/agp.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/agp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/agp.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,44 @@
+#ifndef AGP_H
+#define AGP_H 1
@@ -109691,9 +178673,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/agp.h linux-2.6.18-xen-3
+ dma_free_coherent(NULL,PAGE_SIZE<<(order),(table),virt_to_bus(table))
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/desc.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/desc.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/desc.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/desc.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/desc.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/desc.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/desc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/desc.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,166 @@
+#ifndef __ARCH_DESC_H
+#define __ARCH_DESC_H
@@ -109861,10 +178843,10 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/desc.h linux-2.6.18-xen-
+#endif /* !__ASSEMBLY__ */
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/dma-mapping.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/dma-mapping.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/dma-mapping.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/dma-mapping.h 2008-02-15 16:22:10.000000000 -0800
-@@ -0,0 +1,157 @@
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/dma-mapping.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/dma-mapping.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/dma-mapping.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/dma-mapping.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,151 @@
+#ifndef _ASM_I386_DMA_MAPPING_H
+#define _ASM_I386_DMA_MAPPING_H
+
@@ -109889,13 +178871,7 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/dma-mapping.h linux-2.6.
+ return (addr & ~mask) != 0;
+}
+
-+static inline int
-+range_straddles_page_boundary(paddr_t p, size_t size)
-+{
-+ extern unsigned long *contiguous_bitmap;
-+ return ((((p & ~PAGE_MASK) + size) > PAGE_SIZE) &&
-+ !test_bit(p >> PAGE_SHIFT, contiguous_bitmap));
-+}
++extern int range_straddles_page_boundary(paddr_t p, size_t size);
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
@@ -110022,9 +178998,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/dma-mapping.h linux-2.6.
+ dma_addr_t device_addr, size_t size);
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/fixmap.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/fixmap.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/fixmap.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/fixmap.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/fixmap.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/fixmap.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/fixmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/fixmap.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,155 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
@@ -110181,9 +179157,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/fixmap.h linux-2.6.18-xe
+
+#endif /* !__ASSEMBLY__ */
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/gnttab_dma.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/gnttab_dma.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/gnttab_dma.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/gnttab_dma.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/gnttab_dma.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/gnttab_dma.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/gnttab_dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/gnttab_dma.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
@@ -110226,9 +179202,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/gnttab_dma.h linux-2.6.1
+}
+
+#endif /* _ASM_I386_GNTTAB_DMA_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/highmem.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/highmem.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/highmem.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/highmem.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/highmem.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/highmem.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/highmem.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/highmem.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,80 @@
+/*
+ * highmem.h: virtual kernel memory mappings for high memory
@@ -110310,9 +179286,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/highmem.h linux-2.6.18-x
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_HIGHMEM_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hw_irq.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/hw_irq.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/hw_irq.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/hw_irq.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hw_irq.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/hw_irq.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/hw_irq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/hw_irq.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,72 @@
+#ifndef _ASM_HW_IRQ_H
+#define _ASM_HW_IRQ_H
@@ -110386,9 +179362,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hw_irq.h linux-2.6.18-xe
+#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
+
+#endif /* _ASM_HW_IRQ_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypercall.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/hypercall.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypercall.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/hypercall.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypercall.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/hypercall.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypercall.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/hypercall.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,416 @@
+/******************************************************************************
+ * hypercall.h
@@ -110806,9 +179782,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypercall.h linux-2.6.18
+
+
+#endif /* __HYPERCALL_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypervisor.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/hypervisor.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypervisor.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/hypervisor.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypervisor.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/hypervisor.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypervisor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/hypervisor.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,259 @@
+/******************************************************************************
+ * hypervisor.h
@@ -111069,9 +180045,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/hypervisor.h linux-2.6.1
+#endif
+
+#endif /* __HYPERVISOR_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/io.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/io.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/io.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/io.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/io.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/io.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/io.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/io.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,389 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
@@ -111462,9 +180438,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/io.h linux-2.6.18-xen-3.
+#define ARCH_HAS_DEV_MEM
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/irqflags.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/irqflags.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/irqflags.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/irqflags.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/irqflags.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/irqflags.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/irqflags.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/irqflags.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,127 @@
+/*
+ * include/asm-i386/irqflags.h
@@ -111593,9 +180569,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/irqflags.h linux-2.6.18-
+#endif
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/maddr.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/maddr.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/maddr.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/maddr.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/maddr.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/maddr.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/maddr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/maddr.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,193 @@
+#ifndef _I386_MADDR_H
+#define _I386_MADDR_H
@@ -111753,6 +180729,7 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/maddr.h linux-2.6.18-xen
+#endif
+
+#ifdef CONFIG_X86_PAE
++#define __pte_ma(x) ((pte_t) { (x), (maddr_t)(x) >> 32 } )
+static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
+{
+ pte_t pte;
@@ -111765,11 +180742,10 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/maddr.h linux-2.6.18-xen
+ return pte;
+}
+#else
++#define __pte_ma(x) ((pte_t) { (x) } )
+#define pfn_pte_ma(pfn, prot) __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#endif
+
-+#define __pte_ma(x) ((pte_t) { (x) } )
-+
+#else /* !CONFIG_XEN */
+
+#define pfn_to_mfn(pfn) (pfn)
@@ -111790,42 +180766,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/maddr.h linux-2.6.18-xen
+#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+#endif /* _I386_MADDR_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/mmu.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/mmu.h 2008-02-15 16:22:10.000000000 -0800
-@@ -0,0 +1,29 @@
-+#ifndef __i386_MMU_H
-+#define __i386_MMU_H
-+
-+#include <asm/semaphore.h>
-+/*
-+ * The i386 doesn't have a mmu context, but
-+ * we put the segment information here.
-+ *
-+ * cpu_vm_mask is used to optimize ldt flushing.
-+ */
-+typedef struct {
-+ int size;
-+ struct semaphore sem;
-+ void *ldt;
-+ void *vdso;
-+#ifdef CONFIG_XEN
-+ int has_foreign_mappings;
-+#endif
-+} mm_context_t;
-+
-+/* mm/memory.c:exit_mmap hook */
-+extern void _arch_exit_mmap(struct mm_struct *mm);
-+#define arch_exit_mmap(_mm) _arch_exit_mmap(_mm)
-+
-+/* kernel/fork.c:dup_mmap hook */
-+extern void _arch_dup_mmap(struct mm_struct *mm);
-+#define arch_dup_mmap(mm, oldmm) ((void)(oldmm), _arch_dup_mmap(mm))
-+
-+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu_context.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/mmu_context.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu_context.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/mmu_context.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu_context.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/mmu_context.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu_context.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/mmu_context.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,108 @@
+#ifndef __I386_SCHED_H
+#define __I386_SCHED_H
@@ -111935,10 +180878,43 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu_context.h linux-2.6.
+}
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/page.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/page.h 2008-02-15 16:22:10.000000000 -0800
-@@ -0,0 +1,227 @@
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/mmu.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/mmu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/mmu.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,29 @@
++#ifndef __i386_MMU_H
++#define __i386_MMU_H
++
++#include <asm/semaphore.h>
++/*
++ * The i386 doesn't have a mmu context, but
++ * we put the segment information here.
++ *
++ * cpu_vm_mask is used to optimize ldt flushing.
++ */
++typedef struct {
++ int size;
++ struct semaphore sem;
++ void *ldt;
++ void *vdso;
++#ifdef CONFIG_XEN
++ int has_foreign_mappings;
++#endif
++} mm_context_t;
++
++/* mm/memory.c:exit_mmap hook */
++extern void _arch_exit_mmap(struct mm_struct *mm);
++#define arch_exit_mmap(_mm) _arch_exit_mmap(_mm)
++
++/* kernel/fork.c:dup_mmap hook */
++extern void _arch_dup_mmap(struct mm_struct *mm);
++#define arch_dup_mmap(mm, oldmm) ((void)(oldmm), _arch_dup_mmap(mm))
++
++#endif
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/page.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/page.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,233 @@
+#ifndef _I386_PAGE_H
+#define _I386_PAGE_H
+
@@ -111968,6 +180944,7 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h linux-2.6.18-xen-
+ * below. The preprocessor will warn if the two definitions aren't identical.
+ */
+#define _PAGE_PRESENT 0x001
++#define _PAGE_IO 0x200
+
+#ifndef __ASSEMBLY__
+
@@ -112015,8 +180992,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h linux-2.6.18-xen-
+typedef struct { unsigned long long pgprot; } pgprot_t;
+#define pgprot_val(x) ((x).pgprot)
+#include <asm/maddr.h>
-+#define __pte(x) ({ unsigned long long _x = (x); \
-+ if (_x & _PAGE_PRESENT) _x = pte_phys_to_machine(_x); \
++#define __pte(x) ({ unsigned long long _x = (x); \
++ if ((_x & (_PAGE_PRESENT|_PAGE_IO)) == _PAGE_PRESENT) \
++ _x = pte_phys_to_machine(_x); \
+ ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
+#define __pgd(x) ({ unsigned long long _x = (x); \
+ (pgd_t) {((_x) & _PAGE_PRESENT) ? pte_phys_to_machine(_x) : (_x)}; })
@@ -112029,7 +181007,8 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h linux-2.6.18-xen-
+static inline unsigned long long pte_val(pte_t x)
+{
+ unsigned long long ret = __pte_val(x);
-+ if (x.pte_low & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
++ if ((x.pte_low & (_PAGE_PRESENT|_PAGE_IO)) == _PAGE_PRESENT)
++ ret = pte_machine_to_phys(ret);
+ return ret;
+}
+#define __pmd_val(x) ((x).pmd)
@@ -112060,11 +181039,14 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h linux-2.6.18-xen-
+#include <asm/maddr.h>
+#define boot_pte_t pte_t /* or would you rather have a typedef */
+#define __pte_val(x) ((x).pte_low)
-+#define pte_val(x) (__pte_val(x) & _PAGE_PRESENT ? \
-+ machine_to_phys(__pte_val(x)) : \
-+ __pte_val(x))
-+#define __pte(x) ({ unsigned long _x = (x); \
-+ (pte_t) {((_x) & _PAGE_PRESENT) ? phys_to_machine(_x) : (_x)}; })
++#define pte_val(x) ((__pte_val(x) & (_PAGE_PRESENT|_PAGE_IO)) \
++ == _PAGE_PRESENT ? \
++ machine_to_phys(__pte_val(x)) : \
++ __pte_val(x))
++#define __pte(x) ({ unsigned long _x = (x); \
++ if ((_x & (_PAGE_PRESENT|_PAGE_IO)) == _PAGE_PRESENT) \
++ _x = phys_to_machine(_x); \
++ ((pte_t) { _x }); })
+#define __pmd_val(x) __pud_val((x).pud)
+#define __pud_val(x) __pgd_val((x).pgd)
+#define __pgd(x) ({ unsigned long _x = (x); \
@@ -112166,9 +181148,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/page.h linux-2.6.18-xen-
+#endif /* __KERNEL__ */
+
+#endif /* _I386_PAGE_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pci.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pci.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pci.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pci.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pci.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pci.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pci.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,148 @@
+#ifndef __i386_PCI_H
+#define __i386_PCI_H
@@ -112318,9 +181300,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pci.h linux-2.6.18-xen-3
+#include <asm-generic/pci.h>
+
+#endif /* __i386_PCI_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgalloc.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgalloc.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgalloc.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgalloc.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgalloc.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgalloc.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgalloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgalloc.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,59 @@
+#ifndef _I386_PGALLOC_H
+#define _I386_PGALLOC_H
@@ -112360,8 +181342,8 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgalloc.h linux-2.6.18-x
+
+static inline void pte_free_kernel(pte_t *pte)
+{
-+ free_page((unsigned long)pte);
+ make_lowmem_page_writable(pte, XENFEAT_writable_page_tables);
++ free_page((unsigned long)pte);
+}
+
+extern void pte_free(struct page *pte);
@@ -112381,9 +181363,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgalloc.h linux-2.6.18-x
+#define check_pgt_cache() do { } while (0)
+
+#endif /* _I386_PGALLOC_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,20 @@
+#ifndef _I386_PGTABLE_2LEVEL_DEFS_H
+#define _I386_PGTABLE_2LEVEL_DEFS_H
@@ -112405,10 +181387,10 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level-defs.h li
+#define PTRS_PER_PTE 1024
+
+#endif /* _I386_PGTABLE_2LEVEL_DEFS_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable-2level.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable-2level.h 2008-02-15 16:22:10.000000000 -0800
-@@ -0,0 +1,119 @@
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable-2level.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable-2level.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,121 @@
+#ifndef _I386_PGTABLE_2LEVEL_H
+#define _I386_PGTABLE_2LEVEL_H
+
@@ -112482,8 +181464,10 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level.h linux-2
+#define __pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
+#define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
+ __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte)))
-+#define pte_pfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
-+ mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte))
++#define pte_pfn(_pte) ((_pte).pte_low & _PAGE_IO ? max_mapnr : \
++ (_pte).pte_low & _PAGE_PRESENT ? \
++ mfn_to_local_pfn(__pte_mfn(_pte)) : \
++ __pte_mfn(_pte))
+
+#define pte_page(_pte) pfn_to_page(pte_pfn(_pte))
+
@@ -112528,9 +181512,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-2level.h linux-2
+void vmalloc_sync_all(void);
+
+#endif /* _I386_PGTABLE_2LEVEL_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,24 @@
+#ifndef _I386_PGTABLE_3LEVEL_DEFS_H
+#define _I386_PGTABLE_3LEVEL_DEFS_H
@@ -112556,10 +181540,10 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level-defs.h li
+#define PTRS_PER_PTE 512
+
+#endif /* _I386_PGTABLE_3LEVEL_DEFS_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable-3level.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable-3level.h 2008-02-15 16:22:10.000000000 -0800
-@@ -0,0 +1,209 @@
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable-3level.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable-3level.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,211 @@
+#ifndef _I386_PGTABLE_3LEVEL_H
+#define _I386_PGTABLE_3LEVEL_H
+
@@ -112732,8 +181716,10 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level.h linux-2
+ ((_pte).pte_high << (32-PAGE_SHIFT)))
+#define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
+ __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte)))
-+#define pte_pfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
-+ mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte))
++#define pte_pfn(_pte) ((_pte).pte_low & _PAGE_IO ? max_mapnr : \
++ (_pte).pte_low & _PAGE_PRESENT ? \
++ mfn_to_local_pfn(__pte_mfn(_pte)) : \
++ __pte_mfn(_pte))
+
+extern unsigned long long __supported_pte_mask;
+
@@ -112769,9 +181755,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable-3level.h linux-2
+void vmalloc_sync_all(void);
+
+#endif /* _I386_PGTABLE_3LEVEL_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/pgtable.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/pgtable.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,537 @@
+#ifndef _I386_PGTABLE_H
+#define _I386_PGTABLE_H
@@ -112880,7 +181866,7 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h linux-2.6.18-x
+#define _PAGE_BIT_DIRTY 6
+#define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page, Pentium+, if present.. */
+#define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */
-+#define _PAGE_BIT_UNUSED1 9 /* available for programmer */
++/*#define _PAGE_BIT_UNUSED1 9*/ /* available for programmer */
+#define _PAGE_BIT_UNUSED2 10
+#define _PAGE_BIT_UNUSED3 11
+#define _PAGE_BIT_NX 63
@@ -112894,7 +181880,7 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h linux-2.6.18-x
+#define _PAGE_DIRTY 0x040
+#define _PAGE_PSE 0x080 /* 4 MB (or 2MB) page, Pentium+, if present.. */
+#define _PAGE_GLOBAL 0x100 /* Global TLB entry PPro+ */
-+#define _PAGE_UNUSED1 0x200 /* available for programmer */
++/*#define _PAGE_UNUSED1 0x200*/ /* available for programmer */
+#define _PAGE_UNUSED2 0x400
+#define _PAGE_UNUSED3 0x800
+
@@ -112908,9 +181894,12 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h linux-2.6.18-x
+#define _PAGE_NX 0
+#endif
+
++/* Mapped page is I/O or foreign and has no associated page struct. */
++#define _PAGE_IO 0x200
++
+#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-+#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
++#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_IO)
+
+#define PAGE_NONE \
+ __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
@@ -113249,19 +182238,16 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h linux-2.6.18-x
+void make_pages_readonly(void *va, unsigned int nr, unsigned int feature);
+void make_pages_writable(void *va, unsigned int nr, unsigned int feature);
+
-+#define virt_to_ptep(__va) \
++#define virt_to_ptep(va) \
+({ \
-+ pgd_t *__pgd = pgd_offset_k((unsigned long)(__va)); \
-+ pud_t *__pud = pud_offset(__pgd, (unsigned long)(__va)); \
-+ pmd_t *__pmd = pmd_offset(__pud, (unsigned long)(__va)); \
-+ pte_offset_kernel(__pmd, (unsigned long)(__va)); \
++ pte_t *__ptep = lookup_address((unsigned long)(va)); \
++ BUG_ON(!__ptep || !pte_present(*__ptep)); \
++ __ptep; \
+})
+
-+#define arbitrary_virt_to_machine(__va) \
-+({ \
-+ maddr_t m = (maddr_t)pte_mfn(*virt_to_ptep(__va)) << PAGE_SHIFT;\
-+ m | ((unsigned long)(__va) & (PAGE_SIZE-1)); \
-+})
++#define arbitrary_virt_to_machine(va) \
++ (((maddr_t)pte_mfn(*virt_to_ptep(va)) << PAGE_SHIFT) \
++ | ((unsigned long)(va) & (PAGE_SIZE - 1)))
+
+#endif /* !__ASSEMBLY__ */
+
@@ -113310,9 +182296,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/pgtable.h linux-2.6.18-x
+#include <asm-generic/pgtable.h>
+
+#endif /* _I386_PGTABLE_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/processor.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/processor.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/processor.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/processor.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/processor.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/processor.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/processor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/processor.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,743 @@
+/*
+ * include/asm-i386/processor.h
@@ -114057,9 +183043,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/processor.h linux-2.6.18
+extern int sysenter_setup(void);
+
+#endif /* __ASM_I386_PROCESSOR_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/ptrace.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/ptrace.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/ptrace.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/ptrace.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/ptrace.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/ptrace.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/ptrace.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/ptrace.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,90 @@
+#ifndef _I386_PTRACE_H
+#define _I386_PTRACE_H
@@ -114151,9 +183137,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/ptrace.h linux-2.6.18-xe
+#endif /* __KERNEL__ */
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/scatterlist.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/scatterlist.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/scatterlist.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/scatterlist.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/scatterlist.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/scatterlist.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/scatterlist.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/scatterlist.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,22 @@
+#ifndef _I386_SCATTERLIST_H
+#define _I386_SCATTERLIST_H
@@ -114177,9 +183163,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/scatterlist.h linux-2.6.
+#define ISA_DMA_THRESHOLD (0x00ffffff)
+
+#endif /* !(_I386_SCATTERLIST_H) */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/segment.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/segment.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/segment.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/segment.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/segment.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/segment.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/segment.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/segment.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,117 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
@@ -114298,9 +183284,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/segment.h linux-2.6.18-x
+#define IDT_ENTRIES 256
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/setup.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/setup.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/setup.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/setup.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/setup.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/setup.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/setup.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/setup.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,81 @@
+/*
+ * Just a place holder. We don't want to have to test x86 before
@@ -114383,9 +183369,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/setup.h linux-2.6.18-xen
+#endif /* __ASSEMBLY__ */
+
+#endif /* _i386_SETUP_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/smp.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/smp.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/smp.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/smp.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/smp.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/smp.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/smp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/smp.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,103 @@
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
@@ -114490,9 +183476,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/smp.h linux-2.6.18-xen-3
+
+#endif
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/spinlock.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/spinlock.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/spinlock.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/spinlock.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/spinlock.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/spinlock.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/spinlock.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/spinlock.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,202 @@
+#ifndef __ASM_SPINLOCK_H
+#define __ASM_SPINLOCK_H
@@ -114696,9 +183682,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/spinlock.h linux-2.6.18-
+}
+
+#endif /* __ASM_SPINLOCK_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/swiotlb.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/swiotlb.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/swiotlb.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/swiotlb.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/swiotlb.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/swiotlb.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/swiotlb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/swiotlb.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,43 @@
+#ifndef _ASM_SWIOTLB_H
+#define _ASM_SWIOTLB_H 1
@@ -114743,10 +183729,10 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/swiotlb.h linux-2.6.18-x
+#endif
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/synch_bitops.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/synch_bitops.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/synch_bitops.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/synch_bitops.h 2008-02-15 16:22:10.000000000 -0800
-@@ -0,0 +1,145 @@
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/synch_bitops.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/synch_bitops.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/synch_bitops.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/synch_bitops.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,126 @@
+#ifndef __XEN_SYNCH_BITOPS_H__
+#define __XEN_SYNCH_BITOPS_H__
+
@@ -114868,33 +183854,14 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/synch_bitops.h linux-2.6
+ return old;
+}
+
-+static __always_inline int synch_const_test_bit(int nr,
-+ const volatile void * addr)
-+{
-+ return ((1UL << (nr & 31)) &
-+ (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
-+}
-+
-+static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
-+{
-+ int oldbit;
-+ __asm__ __volatile__ (
-+ "btl %2,%1\n\tsbbl %0,%0"
-+ : "=r" (oldbit) : "m" (ADDR), "Ir" (nr) );
-+ return oldbit;
-+}
-+
-+#define synch_test_bit(nr,addr) \
-+(__builtin_constant_p(nr) ? \
-+ synch_const_test_bit((nr),(addr)) : \
-+ synch_var_test_bit((nr),(addr)))
++#define synch_test_bit test_bit
+
+#define synch_cmpxchg_subword synch_cmpxchg
+
+#endif /* __XEN_SYNCH_BITOPS_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/system.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/system.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/system.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/system.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/system.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/system.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/system.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/system.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,488 @@
+#ifndef __ASM_SYSTEM_H
+#define __ASM_SYSTEM_H
@@ -115384,9 +184351,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/system.h linux-2.6.18-xe
+void default_idle(void);
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/tlbflush.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/tlbflush.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/tlbflush.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/tlbflush.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/tlbflush.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/tlbflush.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/tlbflush.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/tlbflush.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,101 @@
+#ifndef _I386_TLBFLUSH_H
+#define _I386_TLBFLUSH_H
@@ -115489,9 +184456,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/tlbflush.h linux-2.6.18-
+}
+
+#endif /* _I386_TLBFLUSH_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/vga.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/vga.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/vga.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/vga.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/vga.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/vga.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/vga.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/vga.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,20 @@
+/*
+ * Access to VGA videoram
@@ -115513,9 +184480,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/vga.h linux-2.6.18-xen-3
+#define vga_writeb(x,y) (*(y) = (x))
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/xenoprof.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/xenoprof.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/asm/xenoprof.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/asm/xenoprof.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/xenoprof.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/xenoprof.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/asm/xenoprof.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/asm/xenoprof.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,48 @@
+/******************************************************************************
+ * asm-i386/mach-xen/asm/xenoprof.h
@@ -115565,9 +184532,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/asm/xenoprof.h linux-2.6.18-
+
+#endif /* CONFIG_XEN */
+#endif /* __ASM_XENOPROF_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/irq_vectors.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/irq_vectors.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/irq_vectors.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/irq_vectors.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/irq_vectors.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/irq_vectors.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/irq_vectors.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/irq_vectors.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,125 @@
+/*
+ * This file should contain #defines for all of the interrupt vector
@@ -115694,9 +184661,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/irq_vectors.h linux-2.6.18-x
+#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
+
+#endif /* _ASM_IRQ_VECTORS_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/mach_traps.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/mach_traps.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/mach_traps.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/mach_traps.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/mach_traps.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/mach_traps.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/mach_traps.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/mach_traps.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,33 @@
+/*
+ * include/asm-xen/asm-i386/mach-xen/mach_traps.h
@@ -115731,18 +184698,18 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/mach_traps.h linux-2.6.18-xe
+static inline void reassert_nmi(void) {}
+
+#endif /* !_MACH_TRAPS_H */
-diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/setup_arch.h linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/setup_arch.h
---- linux-2.6.18.8/include/asm-i386/mach-xen/setup_arch.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/mach-xen/setup_arch.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/mach-xen/setup_arch.h linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/setup_arch.h
+--- linux-2.6.18.8/include/asm-i386/mach-xen/setup_arch.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/mach-xen/setup_arch.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,5 @@
+/* Hook to call BIOS initialisation function */
+
+#define ARCH_SETUP machine_specific_arch_setup();
+
+void __init machine_specific_arch_setup(void);
-diff -rpuN linux-2.6.18.8/include/asm-i386/page.h linux-2.6.18-xen-3.2.0/include/asm-i386/page.h
---- linux-2.6.18.8/include/asm-i386/page.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/page.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/page.h linux-2.6.18-xen-3.3.0/include/asm-i386/page.h
+--- linux-2.6.18.8/include/asm-i386/page.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/page.h 2008-08-21 11:36:07.000000000 +0200
@@ -122,7 +122,7 @@ extern int page_is_ram(unsigned long pag
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
@@ -115752,9 +184719,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/page.h linux-2.6.18-xen-3.2.0/include
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-diff -rpuN linux-2.6.18.8/include/asm-i386/pgtable-2level-defs.h linux-2.6.18-xen-3.2.0/include/asm-i386/pgtable-2level-defs.h
---- linux-2.6.18.8/include/asm-i386/pgtable-2level-defs.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/pgtable-2level-defs.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/pgtable-2level-defs.h linux-2.6.18-xen-3.3.0/include/asm-i386/pgtable-2level-defs.h
+--- linux-2.6.18.8/include/asm-i386/pgtable-2level-defs.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/pgtable-2level-defs.h 2008-08-21 11:36:07.000000000 +0200
@@ -1,6 +1,8 @@
#ifndef _I386_PGTABLE_2LEVEL_DEFS_H
#define _I386_PGTABLE_2LEVEL_DEFS_H
@@ -115764,9 +184731,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/pgtable-2level-defs.h linux-2.6.18-xe
/*
* traditional i386 two-level paging structure:
*/
-diff -rpuN linux-2.6.18.8/include/asm-i386/pgtable-3level-defs.h linux-2.6.18-xen-3.2.0/include/asm-i386/pgtable-3level-defs.h
---- linux-2.6.18.8/include/asm-i386/pgtable-3level-defs.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-i386/pgtable-3level-defs.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-i386/pgtable-3level-defs.h linux-2.6.18-xen-3.3.0/include/asm-i386/pgtable-3level-defs.h
+--- linux-2.6.18.8/include/asm-i386/pgtable-3level-defs.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-i386/pgtable-3level-defs.h 2008-08-21 11:36:07.000000000 +0200
@@ -1,6 +1,8 @@
#ifndef _I386_PGTABLE_3LEVEL_DEFS_H
#define _I386_PGTABLE_3LEVEL_DEFS_H
@@ -115776,9 +184743,9 @@ diff -rpuN linux-2.6.18.8/include/asm-i386/pgtable-3level-defs.h linux-2.6.18-xe
/*
* PGDIR_SHIFT determines what a top-level page table entry can map
*/
-diff -rpuN linux-2.6.18.8/include/asm-ia64/agp.h linux-2.6.18-xen-3.2.0/include/asm-ia64/agp.h
---- linux-2.6.18.8/include/asm-ia64/agp.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/agp.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/agp.h linux-2.6.18-xen-3.3.0/include/asm-ia64/agp.h
+--- linux-2.6.18.8/include/asm-ia64/agp.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/agp.h 2008-08-21 11:36:07.000000000 +0200
@@ -19,13 +19,44 @@
#define flush_agp_cache() mb()
@@ -115824,9 +184791,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/agp.h linux-2.6.18-xen-3.2.0/include/
+#endif /* CONFIG_XEN */
#endif /* _ASM_IA64_AGP_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/gcc_intrin.h linux-2.6.18-xen-3.2.0/include/asm-ia64/gcc_intrin.h
---- linux-2.6.18.8/include/asm-ia64/gcc_intrin.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/gcc_intrin.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/gcc_intrin.h linux-2.6.18-xen-3.3.0/include/asm-ia64/gcc_intrin.h
+--- linux-2.6.18.8/include/asm-ia64/gcc_intrin.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/gcc_intrin.h 2008-08-21 11:36:07.000000000 +0200
@@ -26,7 +26,7 @@ extern void ia64_bad_param_for_getreg (v
register unsigned long ia64_r13 asm ("r13") __attribute_used__;
@@ -116016,9 +184983,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/gcc_intrin.h linux-2.6.18-xen-3.2.0/i
+#define __ia64_get_psr_i() (__ia64_getreg(_IA64_REG_PSR) & 0x4000UL)
+
#endif /* _ASM_IA64_GCC_INTRIN_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/gnttab_dma.h linux-2.6.18-xen-3.2.0/include/asm-ia64/gnttab_dma.h
---- linux-2.6.18.8/include/asm-ia64/gnttab_dma.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/gnttab_dma.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/gnttab_dma.h linux-2.6.18-xen-3.3.0/include/asm-ia64/gnttab_dma.h
+--- linux-2.6.18.8/include/asm-ia64/gnttab_dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/gnttab_dma.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
@@ -116071,9 +185038,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/gnttab_dma.h linux-2.6.18-xen-3.2.0/i
+}
+
+#endif /* _ASM_IA64_GNTTAB_DMA_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/hw_irq.h linux-2.6.18-xen-3.2.0/include/asm-ia64/hw_irq.h
---- linux-2.6.18.8/include/asm-ia64/hw_irq.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/hw_irq.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/hw_irq.h linux-2.6.18-xen-3.3.0/include/asm-ia64/hw_irq.h
+--- linux-2.6.18.8/include/asm-ia64/hw_irq.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/hw_irq.h 2008-08-21 11:36:07.000000000 +0200
@@ -15,7 +15,11 @@
#include <asm/ptrace.h>
#include <asm/smp.h>
@@ -116099,9 +185066,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/hw_irq.h linux-2.6.18-xen-3.2.0/inclu
platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
}
-diff -rpuN linux-2.6.18.8/include/asm-ia64/hypercall.h linux-2.6.18-xen-3.2.0/include/asm-ia64/hypercall.h
---- linux-2.6.18.8/include/asm-ia64/hypercall.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/hypercall.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/hypercall.h linux-2.6.18-xen-3.3.0/include/asm-ia64/hypercall.h
+--- linux-2.6.18.8/include/asm-ia64/hypercall.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/hypercall.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,458 @@
+/******************************************************************************
+ * hypercall.h
@@ -116561,9 +185528,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/hypercall.h linux-2.6.18-xen-3.2.0/in
+#define HYPERVISOR_mmu_update(req, count, success_count, domid) ({BUG();0;})
+
+#endif /* __HYPERCALL_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/hypervisor.h linux-2.6.18-xen-3.2.0/include/asm-ia64/hypervisor.h
---- linux-2.6.18.8/include/asm-ia64/hypervisor.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/hypervisor.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/hypervisor.h linux-2.6.18-xen-3.3.0/include/asm-ia64/hypervisor.h
+--- linux-2.6.18.8/include/asm-ia64/hypervisor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/hypervisor.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,233 @@
+/******************************************************************************
+ * hypervisor.h
@@ -116798,9 +185765,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/hypervisor.h linux-2.6.18-xen-3.2.0/i
+#endif
+
+#endif /* __HYPERVISOR_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/intel_intrin.h linux-2.6.18-xen-3.2.0/include/asm-ia64/intel_intrin.h
---- linux-2.6.18.8/include/asm-ia64/intel_intrin.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/intel_intrin.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/intel_intrin.h linux-2.6.18-xen-3.3.0/include/asm-ia64/intel_intrin.h
+--- linux-2.6.18.8/include/asm-ia64/intel_intrin.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/intel_intrin.h 2008-08-21 11:36:07.000000000 +0200
@@ -16,8 +16,8 @@
* intrinsic
*/
@@ -116922,9 +185889,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/intel_intrin.h linux-2.6.18-xen-3.2.0
#define __builtin_trap() __break(0);
#endif /* _ASM_IA64_INTEL_INTRIN_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/intrinsics.h linux-2.6.18-xen-3.2.0/include/asm-ia64/intrinsics.h
---- linux-2.6.18.8/include/asm-ia64/intrinsics.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/intrinsics.h 2008-02-15 16:22:10.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/intrinsics.h linux-2.6.18-xen-3.3.0/include/asm-ia64/intrinsics.h
+--- linux-2.6.18.8/include/asm-ia64/intrinsics.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/intrinsics.h 2008-08-21 11:36:07.000000000 +0200
@@ -18,6 +18,15 @@
# include <asm/gcc_intrin.h>
#endif
@@ -116947,9 +185914,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/intrinsics.h linux-2.6.18-xen-3.2.0/i
#endif
+#include <asm/privop.h>
#endif /* _ASM_IA64_INTRINSICS_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/io.h linux-2.6.18-xen-3.2.0/include/asm-ia64/io.h
---- linux-2.6.18.8/include/asm-ia64/io.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/io.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/io.h linux-2.6.18-xen-3.3.0/include/asm-ia64/io.h
+--- linux-2.6.18.8/include/asm-ia64/io.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/io.h 2008-08-21 11:36:07.000000000 +0200
@@ -96,9 +96,39 @@ extern int valid_mmap_phys_addr_range (u
* The following two macros are deprecated and scheduled for removal.
* Please use the PCI-DMA interface defined in <asm/pci.h> instead.
@@ -116990,9 +185957,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/io.h linux-2.6.18-xen-3.2.0/include/a
# endif /* KERNEL */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/iosapic.h linux-2.6.18-xen-3.2.0/include/asm-ia64/iosapic.h
---- linux-2.6.18.8/include/asm-ia64/iosapic.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/iosapic.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/iosapic.h linux-2.6.18-xen-3.3.0/include/asm-ia64/iosapic.h
+--- linux-2.6.18.8/include/asm-ia64/iosapic.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/iosapic.h 2008-08-21 11:36:07.000000000 +0200
@@ -53,6 +53,7 @@
#define NR_IOSAPICS 256
@@ -117009,9 +185976,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/iosapic.h linux-2.6.18-xen-3.2.0/incl
static inline void iosapic_eoi(char __iomem *iosapic, u32 vector)
{
-diff -rpuN linux-2.6.18.8/include/asm-ia64/irq.h linux-2.6.18-xen-3.2.0/include/asm-ia64/irq.h
---- linux-2.6.18.8/include/asm-ia64/irq.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/irq.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/irq.h linux-2.6.18-xen-3.3.0/include/asm-ia64/irq.h
+--- linux-2.6.18.8/include/asm-ia64/irq.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/irq.h 2008-08-21 11:36:07.000000000 +0200
@@ -11,8 +11,41 @@
* 02/29/00 D.Mosberger moved most things into hw_irq.h
*/
@@ -117054,9 +186021,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/irq.h linux-2.6.18-xen-3.2.0/include/
static __inline__ int
irq_canonicalize (int irq)
-diff -rpuN linux-2.6.18.8/include/asm-ia64/kexec.h linux-2.6.18-xen-3.2.0/include/asm-ia64/kexec.h
---- linux-2.6.18.8/include/asm-ia64/kexec.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/kexec.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/kexec.h linux-2.6.18-xen-3.3.0/include/asm-ia64/kexec.h
+--- linux-2.6.18.8/include/asm-ia64/kexec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/kexec.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,58 @@
+#ifndef _ASM_IA64_KEXEC_H
+#define _ASM_IA64_KEXEC_H
@@ -117116,9 +186083,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/kexec.h linux-2.6.18-xen-3.2.0/includ
+#endif
+
+#endif /* _ASM_IA64_KEXEC_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec.h linux-2.6.18-xen-3.2.0/include/asm-ia64/machvec.h
---- linux-2.6.18.8/include/asm-ia64/machvec.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/machvec.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec.h linux-2.6.18-xen-3.3.0/include/asm-ia64/machvec.h
+--- linux-2.6.18.8/include/asm-ia64/machvec.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/machvec.h 2008-08-21 11:36:07.000000000 +0200
@@ -35,6 +35,7 @@ typedef int ia64_mv_pci_legacy_read_t (s
typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
u8 size);
@@ -117154,9 +186121,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec.h linux-2.6.18-xen-3.2.0/incl
#ifndef platform_dma_init
# define platform_dma_init swiotlb_init
#endif
-diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec_sn2.h linux-2.6.18-xen-3.2.0/include/asm-ia64/machvec_sn2.h
---- linux-2.6.18.8/include/asm-ia64/machvec_sn2.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/machvec_sn2.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec_sn2.h linux-2.6.18-xen-3.3.0/include/asm-ia64/machvec_sn2.h
+--- linux-2.6.18.8/include/asm-ia64/machvec_sn2.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/machvec_sn2.h 2008-08-21 11:36:07.000000000 +0200
@@ -67,6 +67,7 @@ extern ia64_mv_dma_sync_sg_for_device sn
extern ia64_mv_dma_mapping_error sn_dma_mapping_error;
extern ia64_mv_dma_supported sn_dma_supported;
@@ -117173,9 +186140,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec_sn2.h linux-2.6.18-xen-3.2.0/
#ifdef CONFIG_PCI_MSI
#define platform_msi_init sn_msi_init
#else
-diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec_xen.h linux-2.6.18-xen-3.2.0/include/asm-ia64/machvec_xen.h
---- linux-2.6.18.8/include/asm-ia64/machvec_xen.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/machvec_xen.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec_xen.h linux-2.6.18-xen-3.3.0/include/asm-ia64/machvec_xen.h
+--- linux-2.6.18.8/include/asm-ia64/machvec_xen.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/machvec_xen.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,43 @@
+#ifndef _ASM_IA64_MACHVEC_XEN_h
+#define _ASM_IA64_MACHVEC_XEN_h
@@ -117220,10 +186187,10 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/machvec_xen.h linux-2.6.18-xen-3.2.0/
+#define platform_dma_mapping_error xen_dma_mapping_error
+
+#endif /* _ASM_IA64_MACHVEC_XEN_h */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/maddr.h linux-2.6.18-xen-3.2.0/include/asm-ia64/maddr.h
---- linux-2.6.18.8/include/asm-ia64/maddr.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/maddr.h 2008-02-15 16:22:11.000000000 -0800
-@@ -0,0 +1,126 @@
+diff -rpuN linux-2.6.18.8/include/asm-ia64/maddr.h linux-2.6.18-xen-3.3.0/include/asm-ia64/maddr.h
+--- linux-2.6.18.8/include/asm-ia64/maddr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/maddr.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,116 @@
+#ifndef _ASM_IA64_MADDR_H
+#define _ASM_IA64_MADDR_H
+
@@ -117334,25 +186301,15 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/maddr.h linux-2.6.18-xen-3.2.0/includ
+#endif
+
+#ifdef CONFIG_XEN
-+static inline int
-+range_straddles_page_boundary(paddr_t p, size_t size)
-+{
-+ extern unsigned long *contiguous_bitmap;
-+
-+ if (!is_running_on_xen())
-+ return 0;
-+
-+ return ((((p & ~PAGE_MASK) + size) > PAGE_SIZE) &&
-+ !test_bit(p >> PAGE_SHIFT, contiguous_bitmap));
-+}
++int range_straddles_page_boundary(paddr_t p, size_t size);
+#else
+#define range_straddles_page_boundary(addr, size) (0)
+#endif
+
+#endif /* _ASM_IA64_MADDR_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/meminit.h linux-2.6.18-xen-3.2.0/include/asm-ia64/meminit.h
---- linux-2.6.18.8/include/asm-ia64/meminit.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/meminit.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/meminit.h linux-2.6.18-xen-3.3.0/include/asm-ia64/meminit.h
+--- linux-2.6.18.8/include/asm-ia64/meminit.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/meminit.h 2008-08-21 11:36:07.000000000 +0200
@@ -15,11 +15,17 @@
* - initrd (optional)
* - command line string
@@ -117372,9 +186329,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/meminit.h linux-2.6.18-xen-3.2.0/incl
struct rsvd_region {
unsigned long start; /* virtual address of beginning of element */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/mmu_context.h linux-2.6.18-xen-3.2.0/include/asm-ia64/mmu_context.h
---- linux-2.6.18.8/include/asm-ia64/mmu_context.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/mmu_context.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/mmu_context.h linux-2.6.18-xen-3.3.0/include/asm-ia64/mmu_context.h
+--- linux-2.6.18.8/include/asm-ia64/mmu_context.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/mmu_context.h 2008-08-21 11:36:07.000000000 +0200
@@ -151,11 +151,7 @@ reload_context (nv_mm_context_t context)
# endif
#endif
@@ -117388,9 +186345,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/mmu_context.h linux-2.6.18-xen-3.2.0/
ia64_srlz_i(); /* srlz.i implies srlz.d */
}
-diff -rpuN linux-2.6.18.8/include/asm-ia64/page.h linux-2.6.18-xen-3.2.0/include/asm-ia64/page.h
---- linux-2.6.18.8/include/asm-ia64/page.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/page.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/page.h linux-2.6.18-xen-3.3.0/include/asm-ia64/page.h
+--- linux-2.6.18.8/include/asm-ia64/page.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/page.h 2008-08-21 11:36:07.000000000 +0200
@@ -119,6 +119,7 @@ extern struct page *vmem_map;
#endif
@@ -117427,9 +186384,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/page.h linux-2.6.18-xen-3.2.0/include
+
# endif /* __KERNEL__ */
#endif /* _ASM_IA64_PAGE_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/pgalloc.h linux-2.6.18-xen-3.2.0/include/asm-ia64/pgalloc.h
---- linux-2.6.18.8/include/asm-ia64/pgalloc.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/pgalloc.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/pgalloc.h linux-2.6.18-xen-3.3.0/include/asm-ia64/pgalloc.h
+--- linux-2.6.18.8/include/asm-ia64/pgalloc.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/pgalloc.h 2008-08-21 11:36:07.000000000 +0200
@@ -125,7 +125,11 @@ static inline void pmd_free(pmd_t * pmd)
static inline void
pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte)
@@ -117442,9 +186399,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/pgalloc.h linux-2.6.18-xen-3.2.0/incl
}
static inline void
-diff -rpuN linux-2.6.18.8/include/asm-ia64/privop.h linux-2.6.18-xen-3.2.0/include/asm-ia64/privop.h
---- linux-2.6.18.8/include/asm-ia64/privop.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/privop.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/privop.h linux-2.6.18-xen-3.3.0/include/asm-ia64/privop.h
+--- linux-2.6.18.8/include/asm-ia64/privop.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/privop.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,63 @@
+#ifndef _ASM_IA64_PRIVOP_H
+#define _ASM_IA64_PRIVOP_H
@@ -117509,9 +186466,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/privop.h linux-2.6.18-xen-3.2.0/inclu
+#endif /* !__ASSEMBLY */
+
+#endif /* _ASM_IA64_PRIVOP_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/sal.h linux-2.6.18-xen-3.2.0/include/asm-ia64/sal.h
---- linux-2.6.18.8/include/asm-ia64/sal.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/sal.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/sal.h linux-2.6.18-xen-3.3.0/include/asm-ia64/sal.h
+--- linux-2.6.18.8/include/asm-ia64/sal.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/sal.h 2008-08-21 11:36:07.000000000 +0200
@@ -42,6 +42,9 @@
#include <asm/pal.h>
#include <asm/system.h>
@@ -117566,9 +186523,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/sal.h linux-2.6.18-xen-3.2.0/include/
SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO, sal_info_type, 0,
sal_info, 0, 0, 0, 0);
if (isrv.status)
-diff -rpuN linux-2.6.18.8/include/asm-ia64/sn/sn_sal.h linux-2.6.18-xen-3.2.0/include/asm-ia64/sn/sn_sal.h
---- linux-2.6.18.8/include/asm-ia64/sn/sn_sal.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/sn/sn_sal.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/sn/sn_sal.h linux-2.6.18-xen-3.3.0/include/asm-ia64/sn/sn_sal.h
+--- linux-2.6.18.8/include/asm-ia64/sn/sn_sal.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/sn/sn_sal.h 2008-08-21 11:36:07.000000000 +0200
@@ -87,6 +87,8 @@
#define SN_SAL_INJECT_ERROR 0x02000067
#define SN_SAL_SET_CPU_NUMBER 0x02000068
@@ -117590,9 +186547,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/sn/sn_sal.h linux-2.6.18-xen-3.2.0/in
+ return rv.status;
+}
#endif /* _ASM_IA64_SN_SN_SAL_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/sn/types.h linux-2.6.18-xen-3.2.0/include/asm-ia64/sn/types.h
---- linux-2.6.18.8/include/asm-ia64/sn/types.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/sn/types.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/sn/types.h linux-2.6.18-xen-3.3.0/include/asm-ia64/sn/types.h
+--- linux-2.6.18.8/include/asm-ia64/sn/types.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/sn/types.h 2008-08-21 11:36:07.000000000 +0200
@@ -20,7 +20,9 @@ typedef unsigned char slotid_t; /* slot
typedef unsigned char slabid_t; /* slab (asic) within slot */
typedef u64 nic_t;
@@ -117603,9 +186560,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/sn/types.h linux-2.6.18-xen-3.2.0/inc
typedef short cnodeid_t;
#endif /* _ASM_IA64_SN_TYPES_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/swiotlb.h linux-2.6.18-xen-3.2.0/include/asm-ia64/swiotlb.h
---- linux-2.6.18.8/include/asm-ia64/swiotlb.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/swiotlb.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/swiotlb.h linux-2.6.18-xen-3.3.0/include/asm-ia64/swiotlb.h
+--- linux-2.6.18.8/include/asm-ia64/swiotlb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/swiotlb.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,41 @@
+#ifndef _ASM_SWIOTLB_H
+#define _ASM_SWIOTLB_H 1
@@ -117648,9 +186605,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/swiotlb.h linux-2.6.18-xen-3.2.0/incl
+#endif
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-ia64/synch_bitops.h linux-2.6.18-xen-3.2.0/include/asm-ia64/synch_bitops.h
---- linux-2.6.18.8/include/asm-ia64/synch_bitops.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/synch_bitops.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/synch_bitops.h linux-2.6.18-xen-3.3.0/include/asm-ia64/synch_bitops.h
+--- linux-2.6.18.8/include/asm-ia64/synch_bitops.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/synch_bitops.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,61 @@
+#ifndef __XEN_SYNCH_BITOPS_H__
+#define __XEN_SYNCH_BITOPS_H__
@@ -117713,9 +186670,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/synch_bitops.h linux-2.6.18-xen-3.2.0
+#define synch_cmpxchg_subword synch_cmpxchg
+
+#endif /* __XEN_SYNCH_BITOPS_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/system.h linux-2.6.18-xen-3.2.0/include/asm-ia64/system.h
---- linux-2.6.18.8/include/asm-ia64/system.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/system.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/system.h linux-2.6.18-xen-3.3.0/include/asm-ia64/system.h
+--- linux-2.6.18.8/include/asm-ia64/system.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/system.h 2008-08-21 11:36:07.000000000 +0200
@@ -123,7 +123,7 @@ extern struct ia64_boot_param {
#define __local_irq_save(x) \
do { \
@@ -117734,10 +186691,10 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/system.h linux-2.6.18-xen-3.2.0/inclu
#define irqs_disabled() \
({ \
-diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/include/asm-ia64/xen/privop.h
---- linux-2.6.18.8/include/asm-ia64/xen/privop.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/xen/privop.h 2008-02-15 16:22:11.000000000 -0800
-@@ -0,0 +1,551 @@
+diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.3.0/include/asm-ia64/xen/privop.h
+--- linux-2.6.18.8/include/asm-ia64/xen/privop.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/xen/privop.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,550 @@
+#ifndef _ASM_IA64_XEN_PRIVOP_H
+#define _ASM_IA64_XEN_PRIVOP_H
+
@@ -117807,8 +186764,7 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+#endif
+
+#ifndef __ASSEMBLY__
-+#define XEN_HYPER_SSM_I asm("break %0" : : "i" (HYPERPRIVOP_SSM_I))
-+#define XEN_HYPER_GET_IVR asm("break %0" : : "i" (HYPERPRIVOP_GET_IVR))
++#define XEN_HYPER_SSM_I asm("break %0" : : "i" (HYPERPRIVOP_SSM_I): "memory")
+
+/************************************************/
+/* Instructions paravirtualized for correctness */
@@ -117823,7 +186779,7 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+xen_fc(unsigned long addr)
+{
+ register __u64 __addr asm ("r8") = addr;
-+ asm volatile ("break %0":: "i"(HYPERPRIVOP_FC), "r"(__addr));
++ asm volatile ("break %0":: "i"(HYPERPRIVOP_FC), "r"(__addr): "memory");
+}
+
+static inline unsigned long
@@ -117928,7 +186884,7 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+xen_set_eflag(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
-+ asm volatile ("break %0":: "i"(HYPERPRIVOP_SET_EFLAG), "r"(__val));
++ asm volatile ("break %0":: "i"(HYPERPRIVOP_SET_EFLAG), "r"(__val): "memory");
+}
+#else
+extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */
@@ -118071,7 +187027,7 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile ("break %0"::
-+ "i"(HYPERPRIVOP_GET_TPR), "r"(__val));
++ "i"(HYPERPRIVOP_GET_TPR), "r"(__val): "memory");
+}
+
+static inline void
@@ -118079,14 +187035,14 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile ("break %0"::
-+ "i"(HYPERPRIVOP_EOI), "r"(__val));
++ "i"(HYPERPRIVOP_EOI), "r"(__val): "memory");
+}
+
+static inline void
+xen_set_itm(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
-+ asm volatile ("break %0":: "i"(HYPERPRIVOP_SET_ITM), "r"(__val));
++ asm volatile ("break %0":: "i"(HYPERPRIVOP_SET_ITM), "r"(__val): "memory");
+}
+
+static inline void
@@ -118095,7 +187051,7 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+ register __u64 __addr asm ("r8") = addr;
+ register __u64 __size asm ("r9") = size;
+ asm volatile ("break %0"::
-+ "i"(HYPERPRIVOP_PTC_GA), "r"(__addr), "r"(__size));
++ "i"(HYPERPRIVOP_PTC_GA), "r"(__addr), "r"(__size): "memory");
+}
+
+static inline unsigned long
@@ -118115,7 +187071,7 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+ register __u64 __index asm ("r8") = index;
+ register __u64 __val asm ("r9") = val;
+ asm volatile ("break %0"::
-+ "i"(HYPERPRIVOP_SET_RR), "r"(__index), "r"(__val));
++ "i"(HYPERPRIVOP_SET_RR), "r"(__index), "r"(__val): "memory");
+}
+
+static inline void
@@ -118130,7 +187086,7 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+ asm volatile ("break %0" ::
+ "i"(HYPERPRIVOP_SET_RR0_TO_RR4),
+ "r"(__val0), "r"(__val1),
-+ "r"(__val2), "r"(__val3), "r"(__val4));
++ "r"(__val2), "r"(__val3), "r"(__val4): "memory");
+}
+
+static inline void
@@ -118139,7 +187095,7 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+ register __u64 __index asm ("r8") = index;
+ register __u64 __val asm ("r9") = val;
+ asm volatile ("break %0"::
-+ "i"(HYPERPRIVOP_SET_KR), "r"(__index), "r"(__val));
++ "i"(HYPERPRIVOP_SET_KR), "r"(__index), "r"(__val): "memory");
+}
+#endif
+
@@ -118289,9 +187245,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/privop.h linux-2.6.18-xen-3.2.0/i
+#define ia64_pal_call_static xen_pal_call_static
+
+#endif /* _ASM_IA64_XEN_PRIVOP_H */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/xcom_hcall.h linux-2.6.18-xen-3.2.0/include/asm-ia64/xen/xcom_hcall.h
---- linux-2.6.18.8/include/asm-ia64/xen/xcom_hcall.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/xen/xcom_hcall.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/xcom_hcall.h linux-2.6.18-xen-3.3.0/include/asm-ia64/xen/xcom_hcall.h
+--- linux-2.6.18.8/include/asm-ia64/xen/xcom_hcall.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/xen/xcom_hcall.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2006 Tristan Gingold <tristan.gingold@bull.net>, Bull SAS
@@ -118360,9 +187316,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/xcom_hcall.h linux-2.6.18-xen-3.2
+extern int xencomm_hypercall_kexec_op(int cmd, void *arg);
+
+#endif /* _LINUX_XENCOMM_HCALL_H_ */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/xencomm.h linux-2.6.18-xen-3.2.0/include/asm-ia64/xen/xencomm.h
---- linux-2.6.18.8/include/asm-ia64/xen/xencomm.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/xen/xencomm.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/xencomm.h linux-2.6.18-xen-3.3.0/include/asm-ia64/xen/xencomm.h
+--- linux-2.6.18.8/include/asm-ia64/xen/xencomm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/xen/xencomm.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation
@@ -118397,9 +187353,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xen/xencomm.h linux-2.6.18-xen-3.2.0/
+#include <xen/xencomm.h>
+
+#endif /* _ASM_IA64_XENCOMM_H_ */
-diff -rpuN linux-2.6.18.8/include/asm-ia64/xenoprof.h linux-2.6.18-xen-3.2.0/include/asm-ia64/xenoprof.h
---- linux-2.6.18.8/include/asm-ia64/xenoprof.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-ia64/xenoprof.h 2008-02-15 16:22:11.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-ia64/xenoprof.h linux-2.6.18-xen-3.3.0/include/asm-ia64/xenoprof.h
+--- linux-2.6.18.8/include/asm-ia64/xenoprof.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-ia64/xenoprof.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,48 @@
+/******************************************************************************
+ * asm-ia64/xenoprof.h
@@ -118449,9 +187405,9 @@ diff -rpuN linux-2.6.18.8/include/asm-ia64/xenoprof.h linux-2.6.18-xen-3.2.0/inc
+
+#endif /* CONFIG_XEN */
+#endif /* __ASM_XENOPROF_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-powerpc/mpic.h linux-2.6.18-xen-3.2.0/include/asm-powerpc/mpic.h
---- linux-2.6.18.8/include/asm-powerpc/mpic.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-powerpc/mpic.h 2008-02-15 16:22:13.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-powerpc/mpic.h linux-2.6.18-xen-3.3.0/include/asm-powerpc/mpic.h
+--- linux-2.6.18.8/include/asm-powerpc/mpic.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-powerpc/mpic.h 2008-08-21 11:36:07.000000000 +0200
@@ -305,6 +305,8 @@ struct mpic
#define MPIC_SPV_EOI 0x00000020
/* No passthrough disable */
@@ -118461,9 +187417,9 @@ diff -rpuN linux-2.6.18.8/include/asm-powerpc/mpic.h linux-2.6.18-xen-3.2.0/incl
/* MPIC HW modification ID */
#define MPIC_REGSET_MASK 0xf0000000
-diff -rpuN linux-2.6.18.8/include/asm-powerpc/udbg.h linux-2.6.18-xen-3.2.0/include/asm-powerpc/udbg.h
---- linux-2.6.18.8/include/asm-powerpc/udbg.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-powerpc/udbg.h 2008-02-15 16:22:13.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-powerpc/udbg.h linux-2.6.18-xen-3.3.0/include/asm-powerpc/udbg.h
+--- linux-2.6.18.8/include/asm-powerpc/udbg.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-powerpc/udbg.h 2008-08-21 11:36:07.000000000 +0200
@@ -42,6 +42,7 @@ extern void __init udbg_init_debug_lpar(
extern void __init udbg_init_pmac_realmode(void);
extern void __init udbg_init_maple_realmode(void);
@@ -118472,9 +187428,9 @@ diff -rpuN linux-2.6.18.8/include/asm-powerpc/udbg.h linux-2.6.18-xen-3.2.0/incl
extern void __init udbg_init_rtas_panel(void);
extern void __init udbg_init_rtas_console(void);
-diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/gnttab_dma.h linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/gnttab_dma.h
---- linux-2.6.18.8/include/asm-powerpc/xen/asm/gnttab_dma.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/gnttab_dma.h 2008-02-15 16:22:13.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/gnttab_dma.h linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/gnttab_dma.h
+--- linux-2.6.18.8/include/asm-powerpc/xen/asm/gnttab_dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/gnttab_dma.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,29 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -118505,9 +187461,9 @@ diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/gnttab_dma.h linux-2.6.18-
+}
+
+#endif /* _ASM_PPC_GNTTAB_DMA_H */
-diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/hypercall.h linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/hypercall.h
---- linux-2.6.18.8/include/asm-powerpc/xen/asm/hypercall.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/hypercall.h 2008-02-15 16:22:13.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/hypercall.h linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/hypercall.h
+--- linux-2.6.18.8/include/asm-powerpc/xen/asm/hypercall.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/hypercall.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,90 @@
+/******************************************************************************
+ * hypercall.h
@@ -118599,9 +187555,9 @@ diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/hypercall.h linux-2.6.18-x
+extern int privcmd_hypercall(struct privcmd_hypercall *hypercall);
+
+#endif /* __HYPERCALL_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/hypervisor.h linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/hypervisor.h
---- linux-2.6.18.8/include/asm-powerpc/xen/asm/hypervisor.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/hypervisor.h 2008-02-15 16:22:13.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/hypervisor.h linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/hypervisor.h
+--- linux-2.6.18.8/include/asm-powerpc/xen/asm/hypervisor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/hypervisor.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,276 @@
+/******************************************************************************
+ * hypervisor.h
@@ -118879,9 +187835,9 @@ diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/hypervisor.h linux-2.6.18-
+ })
+
+#endif /* __HYPERVISOR_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/maddr.h linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/maddr.h
---- linux-2.6.18.8/include/asm-powerpc/xen/asm/maddr.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/maddr.h 2008-02-15 16:22:13.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/maddr.h linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/maddr.h
+--- linux-2.6.18.8/include/asm-powerpc/xen/asm/maddr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/maddr.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,7 @@
+#ifndef _POWERPC_MADDR_H
+#define _POWERPC_MADDR_H
@@ -118890,9 +187846,9 @@ diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/maddr.h linux-2.6.18-xen-3
+#include <xen/interface/xen.h>
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/synch_bitops.h linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/synch_bitops.h
---- linux-2.6.18.8/include/asm-powerpc/xen/asm/synch_bitops.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-powerpc/xen/asm/synch_bitops.h 2008-02-15 16:22:13.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/synch_bitops.h linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/synch_bitops.h
+--- linux-2.6.18.8/include/asm-powerpc/xen/asm/synch_bitops.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-powerpc/xen/asm/synch_bitops.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,100 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -118994,21 +187950,56 @@ diff -rpuN linux-2.6.18.8/include/asm-powerpc/xen/asm/synch_bitops.h linux-2.6.1
+#endif
+
+#endif /* __SYNCH_BITOPS_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/acpi.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/acpi.h
---- linux-2.6.18.8/include/asm-x86_64/acpi.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/acpi.h 2008-02-15 16:22:14.000000000 -0800
-@@ -153,6 +153,10 @@ extern unsigned long acpi_wakeup_address
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/acpi.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/acpi.h
+--- linux-2.6.18.8/include/asm-x86_64/acpi.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/acpi.h 2008-08-21 11:36:07.000000000 +0200
+@@ -28,6 +28,9 @@
+
+ #ifdef __KERNEL__
+
++#ifdef CONFIG_XEN
++#include <xen/interface/platform.h>
++#endif
+ #include <acpi/pdc_intel.h>
+
+ #define COMPILER_DEPENDENT_INT64 long long
+@@ -129,6 +132,27 @@ static inline void acpi_disable_pci(void
+ }
+ extern int acpi_irq_balance_set(char *str);
+
++#ifdef CONFIG_XEN
++static inline int acpi_notify_hypervisor_state(u8 sleep_state,
++ u32 pm1a_cnt_val,
++ u32 pm1b_cnt_val)
++{
++ struct xen_platform_op op = {
++ .cmd = XENPF_enter_acpi_sleep,
++ .interface_version = XENPF_INTERFACE_VERSION,
++ .u = {
++ .enter_acpi_sleep = {
++ .pm1a_cnt_val = pm1a_cnt_val,
++ .pm1b_cnt_val = pm1b_cnt_val,
++ .sleep_state = sleep_state,
++ },
++ },
++ };
++
++ return HYPERVISOR_platform_op(&op);
++}
++#endif /* CONFIG_XEN */
++
+ #else /* !CONFIG_ACPI */
+
+ #define acpi_lapic 0
+@@ -152,7 +176,6 @@ extern unsigned long acpi_wakeup_address
+
/* early initialization routine */
extern void acpi_reserve_bootmem(void);
-
-+#ifdef CONFIG_ACPI_PV_SLEEP
-+extern int acpi_notify_hypervisor_state(u8 sleep_state,
-+ u32 pm1a_cnt, u32 pm1b_cnt);
-+#endif /* CONFIG_ACPI_PV_SLEEP */
+-
#endif /*CONFIG_ACPI_SLEEP*/
#define boot_cpu_physical_apicid boot_cpu_id
-@@ -162,7 +166,9 @@ extern int acpi_pci_disabled;
+@@ -162,7 +185,9 @@ extern int acpi_pci_disabled;
extern u8 x86_acpiid_to_apicid[];
@@ -119018,9 +188009,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/acpi.h linux-2.6.18-xen-3.2.0/inclu
extern int acpi_skip_timer_override;
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/agp.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/agp.h
---- linux-2.6.18.8/include/asm-x86_64/agp.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/agp.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/agp.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/agp.h
+--- linux-2.6.18.8/include/asm-x86_64/agp.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/agp.h 2008-08-21 11:36:07.000000000 +0200
@@ -10,8 +10,10 @@
* with different cachability attributes for the same page.
*/
@@ -119034,9 +188025,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/agp.h linux-2.6.18-xen-3.2.0/includ
#define flush_agp_mappings() global_flush_tlb()
/* Could use CLFLUSH here if the cpu supports it. But then it would
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/apic.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/apic.h
---- linux-2.6.18.8/include/asm-x86_64/apic.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/apic.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/apic.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/apic.h
+--- linux-2.6.18.8/include/asm-x86_64/apic.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/apic.h 2008-08-21 11:36:07.000000000 +0200
@@ -98,11 +98,13 @@ extern void setup_APIC_extened_lvt(unsig
extern int disable_timer_pin_1;
@@ -119051,9 +188042,21 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/apic.h linux-2.6.18-xen-3.2.0/inclu
#endif /* CONFIG_X86_LOCAL_APIC */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/kexec.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/kexec.h
---- linux-2.6.18.8/include/asm-x86_64/kexec.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/kexec.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/io_apic.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/io_apic.h
+--- linux-2.6.18.8/include/asm-x86_64/io_apic.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/io_apic.h 2008-08-21 11:36:07.000000000 +0200
+@@ -12,7 +12,7 @@
+
+ #ifdef CONFIG_X86_IO_APIC
+
+-#ifdef CONFIG_PCI_MSI
++#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+ static inline int use_pci_vector(void) {return 1;}
+ static inline void disable_edge_ioapic_vector(unsigned int vector) { }
+ static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/kexec.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/kexec.h
+--- linux-2.6.18.8/include/asm-x86_64/kexec.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/kexec.h 2008-08-21 11:36:07.000000000 +0200
@@ -1,6 +1,27 @@
#ifndef _X86_64_KEXEC_H
#define _X86_64_KEXEC_H
@@ -119108,9 +188111,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/kexec.h linux-2.6.18-xen-3.2.0/incl
+#endif /* __ASSEMBLY__ */
+
#endif /* _X86_64_KEXEC_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/agp.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/agp.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/agp.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/agp.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/agp.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/agp.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/agp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/agp.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,40 @@
+#ifndef AGP_H
+#define AGP_H 1
@@ -119152,9 +188155,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/agp.h linux-2.6.18-xen
+ dma_free_coherent(NULL,PAGE_SIZE<<(order),(table),virt_to_bus(table))
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/arch_hooks.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/arch_hooks.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/arch_hooks.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/arch_hooks.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/arch_hooks.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/arch_hooks.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/arch_hooks.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/arch_hooks.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,27 @@
+#ifndef _ASM_ARCH_HOOKS_H
+#define _ASM_ARCH_HOOKS_H
@@ -119183,9 +188186,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/arch_hooks.h linux-2.6
+extern void mca_nmi_hook(void);
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/bootsetup.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/bootsetup.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/bootsetup.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/bootsetup.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/bootsetup.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/bootsetup.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/bootsetup.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/bootsetup.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,42 @@
+
+#ifndef _X86_64_BOOTSETUP_H
@@ -119229,9 +188232,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/bootsetup.h linux-2.6.
+#define RAMDISK_LOAD_FLAG 0x4000
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/desc.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/desc.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/desc.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/desc.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/desc.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/desc.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/desc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/desc.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,265 @@
+/* Written 2000 by Andi Kleen */
+#ifndef __ARCH_DESC_H
@@ -119498,9 +188501,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/desc.h linux-2.6.18-xe
+#endif /* !__ASSEMBLY__ */
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/dma-mapping.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/dma-mapping.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/dma-mapping.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/dma-mapping.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/dma-mapping.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/dma-mapping.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/dma-mapping.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/dma-mapping.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,207 @@
+#ifndef _X8664_DMA_MAPPING_H
+#define _X8664_DMA_MAPPING_H 1
@@ -119709,9 +188712,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/dma-mapping.h linux-2.
+#endif /* _X8664_DMA_MAPPING_H */
+
+#include <asm-i386/mach-xen/asm/dma-mapping.h>
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/e820.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/e820.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/e820.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/e820.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/e820.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/e820.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/e820.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/e820.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,66 @@
+/*
+ * structures and definitions for the int 15, ax=e820 memory map
@@ -119779,9 +188782,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/e820.h linux-2.6.18-xe
+#endif/*!__ASSEMBLY__*/
+
+#endif/*__E820_HEADER*/
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/fixmap.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/fixmap.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/fixmap.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/fixmap.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/fixmap.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/fixmap.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/fixmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/fixmap.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,112 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
@@ -119895,14 +188898,14 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/fixmap.h linux-2.6.18-
+}
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/gnttab_dma.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/gnttab_dma.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/gnttab_dma.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/gnttab_dma.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/gnttab_dma.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/gnttab_dma.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/gnttab_dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/gnttab_dma.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1 @@
+#include <asm-i386/mach-xen/asm/gnttab_dma.h>
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hw_irq.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/hw_irq.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hw_irq.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/hw_irq.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hw_irq.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/hw_irq.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hw_irq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/hw_irq.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,136 @@
+#ifndef _ASM_HW_IRQ_H
+#define _ASM_HW_IRQ_H
@@ -120040,9 +189043,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hw_irq.h linux-2.6.18-
+#endif
+
+#endif /* _ASM_HW_IRQ_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypercall.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/hypercall.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypercall.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/hypercall.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypercall.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/hypercall.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypercall.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/hypercall.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,415 @@
+/******************************************************************************
+ * hypercall.h
@@ -120459,15 +189462,15 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypercall.h linux-2.6.
+}
+
+#endif /* __HYPERCALL_H__ */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypervisor.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/hypervisor.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypervisor.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/hypervisor.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypervisor.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/hypervisor.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/hypervisor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/hypervisor.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,2 @@
+
+#include <asm-i386/mach-xen/asm/hypervisor.h>
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/io.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/io.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/io.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/io.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/io.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/io.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/io.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/io.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,329 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
@@ -120798,51 +189801,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/io.h linux-2.6.18-xen-
+#define ARCH_HAS_DEV_MEM
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irq.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/irq.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irq.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/irq.h 2008-02-15 16:22:14.000000000 -0800
-@@ -0,0 +1,38 @@
-+#ifndef _ASM_IRQ_H
-+#define _ASM_IRQ_H
-+
-+/*
-+ * linux/include/asm/irq.h
-+ *
-+ * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
-+ *
-+ * IRQ/IPI changes taken from work by Thomas Radke
-+ * <tomsoft@informatik.tu-chemnitz.de>
-+ */
-+
-+#include <linux/sched.h>
-+/* include comes from machine specific directory */
-+#include "irq_vectors.h"
-+#include <asm/thread_info.h>
-+
-+static __inline__ int irq_canonicalize(int irq)
-+{
-+ return ((irq == 2) ? 9 : irq);
-+}
-+
-+#ifdef CONFIG_X86_LOCAL_APIC
-+#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
-+#endif
-+
-+#define KDB_VECTOR 0xf9
-+
-+# define irq_ctx_init(cpu) do { } while (0)
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+#include <linux/cpumask.h>
-+extern void fixup_irqs(cpumask_t map);
-+#endif
-+
-+#define __ARCH_HAS_DO_SOFTIRQ 1
-+
-+#endif /* _ASM_IRQ_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irqflags.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/irqflags.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irqflags.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/irqflags.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irqflags.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/irqflags.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irqflags.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/irqflags.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,139 @@
+/*
+ * include/asm-x86_64/irqflags.h
@@ -120983,9 +189944,51 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irqflags.h linux-2.6.1
+#endif
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/maddr.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/maddr.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/maddr.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/maddr.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irq.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/irq.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/irq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/irq.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,38 @@
++#ifndef _ASM_IRQ_H
++#define _ASM_IRQ_H
++
++/*
++ * linux/include/asm/irq.h
++ *
++ * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
++ *
++ * IRQ/IPI changes taken from work by Thomas Radke
++ * <tomsoft@informatik.tu-chemnitz.de>
++ */
++
++#include <linux/sched.h>
++/* include comes from machine specific directory */
++#include "irq_vectors.h"
++#include <asm/thread_info.h>
++
++static __inline__ int irq_canonicalize(int irq)
++{
++ return ((irq == 2) ? 9 : irq);
++}
++
++#ifdef CONFIG_X86_LOCAL_APIC
++#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
++#endif
++
++#define KDB_VECTOR 0xf9
++
++# define irq_ctx_init(cpu) do { } while (0)
++
++#ifdef CONFIG_HOTPLUG_CPU
++#include <linux/cpumask.h>
++extern void fixup_irqs(cpumask_t map);
++#endif
++
++#define __ARCH_HAS_DO_SOFTIRQ 1
++
++#endif /* _ASM_IRQ_H */
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/maddr.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/maddr.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/maddr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/maddr.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,161 @@
+#ifndef _X86_64_MADDR_H
+#define _X86_64_MADDR_H
@@ -121148,51 +190151,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/maddr.h linux-2.6.18-x
+
+#endif /* _X86_64_MADDR_H */
+
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/mmu.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/mmu.h 2008-02-15 16:22:14.000000000 -0800
-@@ -0,0 +1,38 @@
-+#ifndef __x86_64_MMU_H
-+#define __x86_64_MMU_H
-+
-+#include <linux/spinlock.h>
-+#include <asm/semaphore.h>
-+
-+/*
-+ * The x86_64 doesn't have a mmu context, but
-+ * we put the segment information here.
-+ *
-+ * cpu_vm_mask is used to optimize ldt flushing.
-+ */
-+typedef struct {
-+ void *ldt;
-+ rwlock_t ldtlock;
-+ int size;
-+ struct semaphore sem;
-+#ifdef CONFIG_XEN
-+ unsigned pinned:1;
-+ unsigned has_foreign_mappings:1;
-+ struct list_head unpinned;
-+#endif
-+} mm_context_t;
-+
-+#ifdef CONFIG_XEN
-+extern struct list_head mm_unpinned;
-+extern spinlock_t mm_unpinned_lock;
-+
-+/* mm/memory.c:exit_mmap hook */
-+extern void _arch_exit_mmap(struct mm_struct *mm);
-+#define arch_exit_mmap(_mm) _arch_exit_mmap(_mm)
-+
-+/* kernel/fork.c:dup_mmap hook */
-+extern void _arch_dup_mmap(struct mm_struct *mm);
-+#define arch_dup_mmap(mm, oldmm) ((void)(oldmm), _arch_dup_mmap(mm))
-+#endif
-+
-+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu_context.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/mmu_context.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu_context.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/mmu_context.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu_context.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/mmu_context.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu_context.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/mmu_context.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,136 @@
+#ifndef __X86_64_MMU_CONTEXT_H
+#define __X86_64_MMU_CONTEXT_H
@@ -121330,9 +190291,51 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu_context.h linux-2.
+}
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/msr.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/msr.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/msr.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/msr.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/mmu.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/mmu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/mmu.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,38 @@
++#ifndef __x86_64_MMU_H
++#define __x86_64_MMU_H
++
++#include <linux/spinlock.h>
++#include <asm/semaphore.h>
++
++/*
++ * The x86_64 doesn't have a mmu context, but
++ * we put the segment information here.
++ *
++ * cpu_vm_mask is used to optimize ldt flushing.
++ */
++typedef struct {
++ void *ldt;
++ rwlock_t ldtlock;
++ int size;
++ struct semaphore sem;
++#ifdef CONFIG_XEN
++ unsigned pinned:1;
++ unsigned has_foreign_mappings:1;
++ struct list_head unpinned;
++#endif
++} mm_context_t;
++
++#ifdef CONFIG_XEN
++extern struct list_head mm_unpinned;
++extern spinlock_t mm_unpinned_lock;
++
++/* mm/memory.c:exit_mmap hook */
++extern void _arch_exit_mmap(struct mm_struct *mm);
++#define arch_exit_mmap(_mm) _arch_exit_mmap(_mm)
++
++/* kernel/fork.c:dup_mmap hook */
++extern void _arch_dup_mmap(struct mm_struct *mm);
++#define arch_dup_mmap(mm, oldmm) ((void)(oldmm), _arch_dup_mmap(mm))
++#endif
++
++#endif
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/msr.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/msr.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/msr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/msr.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,399 @@
+#ifndef X86_64_MSR_H
+#define X86_64_MSR_H 1
@@ -121733,9 +190736,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/msr.h linux-2.6.18-xen
+#define MSR_P4_U2L_ESCR1 0x3b1
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/nmi.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/nmi.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/nmi.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/nmi.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/nmi.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/nmi.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/nmi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/nmi.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,93 @@
+/*
+ * linux/include/asm-i386/nmi.h
@@ -121830,10 +190833,10 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/nmi.h linux-2.6.18-xen
+#define NMI_INVALID 3
+
+#endif /* ASM_NMI_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/page.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/page.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/page.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/page.h 2008-02-15 16:22:14.000000000 -0800
-@@ -0,0 +1,209 @@
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/page.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/page.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/page.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/page.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,212 @@
+#ifndef _X86_64_PAGE_H
+#define _X86_64_PAGE_H
+
@@ -121851,6 +190854,7 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/page.h linux-2.6.18-xe
+ * below. The preprocessor will warn if the two definitions aren't identical.
+ */
+#define _PAGE_PRESENT 0x001
++#define _PAGE_IO 0x200
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT 12
@@ -121925,9 +190929,10 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/page.h linux-2.6.18-xe
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define __pte_val(x) ((x).pte)
-+#define pte_val(x) ((__pte_val(x) & _PAGE_PRESENT) ? \
-+ pte_machine_to_phys(__pte_val(x)) : \
-+ __pte_val(x))
++#define pte_val(x) ((__pte_val(x) & (_PAGE_PRESENT|_PAGE_IO)) \
++ == _PAGE_PRESENT ? \
++ pte_machine_to_phys(__pte_val(x)) : \
++ __pte_val(x))
+
+#define __pmd_val(x) ((x).pmd)
+static inline unsigned long pmd_val(pmd_t x)
@@ -121961,7 +190966,8 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/page.h linux-2.6.18-xe
+
+static inline pte_t __pte(unsigned long x)
+{
-+ if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x);
++ if ((x & (_PAGE_PRESENT|_PAGE_IO)) == _PAGE_PRESENT)
++ x = pte_phys_to_machine(x);
+ return ((pte_t) { (x) });
+}
+
@@ -122043,9 +191049,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/page.h linux-2.6.18-xe
+#endif /* __KERNEL__ */
+
+#endif /* _X86_64_PAGE_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pci.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/pci.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pci.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/pci.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pci.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/pci.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/pci.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,168 @@
+#ifndef __x8664_PCI_H
+#define __x8664_PCI_H
@@ -122215,9 +191221,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pci.h linux-2.6.18-xen
+#endif
+
+#endif /* __x8664_PCI_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgalloc.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/pgalloc.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgalloc.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/pgalloc.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgalloc.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/pgalloc.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgalloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/pgalloc.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,204 @@
+#ifndef _X86_64_PGALLOC_H
+#define _X86_64_PGALLOC_H
@@ -122423,10 +191429,10 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgalloc.h linux-2.6.18
+#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
+
+#endif /* _X86_64_PGALLOC_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/pgtable.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/pgtable.h 2008-02-15 16:22:14.000000000 -0800
-@@ -0,0 +1,579 @@
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/pgtable.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/pgtable.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,583 @@
+#ifndef _X86_64_PGTABLE_H
+#define _X86_64_PGTABLE_H
+
@@ -122447,19 +191453,18 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h linux-2.6.18
+
+extern void xen_init_pt(void);
+
-+#define virt_to_ptep(__va) \
-+({ \
-+ pgd_t *__pgd = pgd_offset_k((unsigned long)(__va)); \
-+ pud_t *__pud = pud_offset(__pgd, (unsigned long)(__va)); \
-+ pmd_t *__pmd = pmd_offset(__pud, (unsigned long)(__va)); \
-+ pte_offset_kernel(__pmd, (unsigned long)(__va)); \
-+})
++extern pte_t *lookup_address(unsigned long address);
+
-+#define arbitrary_virt_to_machine(__va) \
++#define virt_to_ptep(va) \
+({ \
-+ maddr_t m = (maddr_t)pte_mfn(*virt_to_ptep(__va)) << PAGE_SHIFT;\
-+ m | ((unsigned long)(__va) & (PAGE_SIZE-1)); \
++ pte_t *__ptep = lookup_address((unsigned long)(va)); \
++ BUG_ON(!__ptep || !pte_present(*__ptep)); \
++ __ptep; \
+})
++
++#define arbitrary_virt_to_machine(va) \
++ (((maddr_t)pte_mfn(*virt_to_ptep(va)) << PAGE_SHIFT) \
++ | ((unsigned long)(va) & (PAGE_SIZE - 1)))
+#endif
+
+extern pud_t level3_kernel_pgt[512];
@@ -122597,6 +191602,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h linux-2.6.18
+#define _PAGE_PROTNONE 0x080 /* If not present */
+#define _PAGE_NX (1UL<<_PAGE_BIT_NX)
+
++/* Mapped page is I/O or foreign and has no associated page struct. */
++#define _PAGE_IO 0x200
++
+#if CONFIG_XEN_COMPAT <= 0x030002
+extern unsigned int __kernel_page_user;
+#else
@@ -122606,7 +191614,7 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h linux-2.6.18
+#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | __kernel_page_user)
+
-+#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
++#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_IO)
+
+#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
@@ -122697,8 +191705,10 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h linux-2.6.18
+#define __pte_mfn(_pte) (((_pte).pte & PTE_MASK) >> PAGE_SHIFT)
+#define pte_mfn(_pte) ((_pte).pte & _PAGE_PRESENT ? \
+ __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte)))
-+#define pte_pfn(_pte) ((_pte).pte & _PAGE_PRESENT ? \
-+ mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte))
++#define pte_pfn(_pte) ((_pte).pte & _PAGE_IO ? end_pfn : \
++ (_pte).pte & _PAGE_PRESENT ? \
++ mfn_to_local_pfn(__pte_mfn(_pte)) : \
++ __pte_mfn(_pte))
+
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
@@ -123006,10 +192016,10 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/pgtable.h linux-2.6.18
+#include <asm-generic/pgtable.h>
+
+#endif /* _X86_64_PGTABLE_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/processor.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/processor.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/processor.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/processor.h 2008-02-15 16:22:14.000000000 -0800
-@@ -0,0 +1,508 @@
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/processor.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/processor.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/processor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/processor.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,502 @@
+/*
+ * include/asm-x86_64/processor.h
+ *
@@ -123180,12 +192190,6 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/processor.h linux-2.6.
+
+
+/*
-+ * Bus types
-+ */
-+#define MCA_bus 0
-+#define MCA_bus__is_a_macro
-+
-+/*
+ * User space process size. 47bits minus one guard page.
+ */
+#define TASK_SIZE64 (0x800000000000UL - 4096)
@@ -123518,9 +192522,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/processor.h linux-2.6.
+#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
+
+#endif /* __ASM_X86_64_PROCESSOR_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/ptrace.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/ptrace.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/ptrace.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/ptrace.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/ptrace.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/ptrace.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/ptrace.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/ptrace.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,127 @@
+#ifndef _X86_64_PTRACE_H
+#define _X86_64_PTRACE_H
@@ -123649,9 +192653,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/ptrace.h linux-2.6.18-
+#endif
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/smp.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/smp.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/smp.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/smp.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/smp.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/smp.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/smp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/smp.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,150 @@
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
@@ -123803,15 +192807,15 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/smp.h linux-2.6.18-xen
+
+#endif
+
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/synch_bitops.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/synch_bitops.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/synch_bitops.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/synch_bitops.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/synch_bitops.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/synch_bitops.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/synch_bitops.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/synch_bitops.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,2 @@
+
+#include <asm-i386/mach-xen/asm/synch_bitops.h>
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/system.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/system.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/system.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/system.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/system.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/system.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/system.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/system.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,256 @@
+#ifndef __ASM_SYSTEM_H
+#define __ASM_SYSTEM_H
@@ -124069,9 +193073,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/system.h linux-2.6.18-
+extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/timer.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/timer.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/timer.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/timer.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/timer.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/timer.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/timer.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/timer.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,67 @@
+#ifndef _ASMi386_TIMER_H
+#define _ASMi386_TIMER_H
@@ -124140,9 +193144,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/timer.h linux-2.6.18-x
+extern struct init_timer_opts timer_pmtmr_init;
+#endif
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/tlbflush.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/tlbflush.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/tlbflush.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/tlbflush.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/tlbflush.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/tlbflush.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/tlbflush.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/tlbflush.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,103 @@
+#ifndef _X8664_TLBFLUSH_H
+#define _X8664_TLBFLUSH_H
@@ -124247,9 +193251,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/tlbflush.h linux-2.6.1
+}
+
+#endif /* _X8664_TLBFLUSH_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/vga.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/vga.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/vga.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/vga.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/vga.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/vga.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/vga.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/vga.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,20 @@
+/*
+ * Access to VGA videoram
@@ -124271,14 +193275,14 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/vga.h linux-2.6.18-xen
+#define vga_writeb(x,y) (*(y) = (x))
+
+#endif
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xenoprof.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/xenoprof.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xenoprof.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/xenoprof.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xenoprof.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/xenoprof.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xenoprof.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/xenoprof.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1 @@
+#include <asm-i386/mach-xen/asm/xenoprof.h>
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xor.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/xor.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xor.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/asm/xor.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xor.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/xor.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/asm/xor.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,328 @@
+/*
+ * x86-64 changes / gcc fixes from Andi Kleen.
@@ -124608,9 +193612,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/asm/xor.h linux-2.6.18-xen
+ We may also be able to load into the L1 only depending on how the cpu
+ deals with a load to a line that is being prefetched. */
+#define XOR_SELECT_TEMPLATE(FASTEST) (&xor_block_sse)
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/irq_vectors.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/irq_vectors.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/irq_vectors.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/irq_vectors.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/irq_vectors.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/irq_vectors.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/irq_vectors.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/irq_vectors.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,123 @@
+/*
+ * This file should contain #defines for all of the interrupt vector
@@ -124735,9 +193739,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/irq_vectors.h linux-2.6.18
+#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
+
+#endif /* _ASM_IRQ_VECTORS_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_time.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/mach_time.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_time.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/mach_time.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_time.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/mach_time.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_time.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/mach_time.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,111 @@
+/*
+ * include/asm-i386/mach-default/mach_time.h
@@ -124850,9 +193854,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_time.h linux-2.6.18-x
+}
+
+#endif /* !_MACH_TIME_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_timer.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/mach_timer.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_timer.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/mach_timer.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_timer.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/mach_timer.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_timer.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/mach_timer.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,50 @@
+/*
+ * include/asm-i386/mach-default/mach_timer.h
@@ -124904,9 +193908,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/mach_timer.h linux-2.6.18-
+}
+
+#endif /* !_MACH_TIMER_H */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_post.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/setup_arch_post.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_post.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/setup_arch_post.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_post.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/setup_arch_post.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_post.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/setup_arch_post.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,63 @@
+/**
+ * machine_specific_* - Hooks for machine specific setup.
@@ -124971,18 +193975,44 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_post.h linux-2.
+#endif
+#endif
+}
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_pre.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/setup_arch_pre.h
---- linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_pre.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/mach-xen/setup_arch_pre.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_pre.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/setup_arch_pre.h
+--- linux-2.6.18.8/include/asm-x86_64/mach-xen/setup_arch_pre.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/mach-xen/setup_arch_pre.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,5 @@
+/* Hook to call BIOS initialisation function */
+
+#define ARCH_SETUP machine_specific_arch_setup();
+
+static void __init machine_specific_arch_setup(void);
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/signal.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/signal.h
---- linux-2.6.18.8/include/asm-x86_64/signal.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/signal.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/msi.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/msi.h
+--- linux-2.6.18.8/include/asm-x86_64/msi.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/msi.h 2008-08-21 11:36:07.000000000 +0200
+@@ -7,14 +7,21 @@
+ #define ASM_MSI_H
+
+ #include <asm/desc.h>
++#ifndef CONFIG_XEN
+ #include <asm/mach_apic.h>
++#endif
+ #include <asm/smp.h>
+
++#ifndef CONFIG_XEN
+ #define LAST_DEVICE_VECTOR (FIRST_SYSTEM_VECTOR - 1)
++#else
++#define LAST_DYNAMIC_VECTOR 0xdf
++#define LAST_DEVICE_VECTOR (LAST_DYNAMIC_VECTOR)
++#endif
++
+ #define MSI_TARGET_CPU_SHIFT 12
+
+ extern struct msi_ops msi_apic_ops;
+-
+ static inline int msi_arch_init(void)
+ {
+ msi_register(&msi_apic_ops);
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/signal.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/signal.h
+--- linux-2.6.18.8/include/asm-x86_64/signal.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/signal.h 2008-08-21 11:36:07.000000000 +0200
@@ -24,10 +24,6 @@ typedef struct {
} sigset_t;
@@ -124994,9 +194024,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/signal.h linux-2.6.18-xen-3.2.0/inc
#else
/* Here we must cater to libcs that poke about in kernel headers. */
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/thread_info.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/thread_info.h
---- linux-2.6.18.8/include/asm-x86_64/thread_info.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/thread_info.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/thread_info.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/thread_info.h
+--- linux-2.6.18.8/include/asm-x86_64/thread_info.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/thread_info.h 2008-08-21 11:36:07.000000000 +0200
@@ -114,6 +114,7 @@ static inline struct thread_info *stack_
#define TIF_IRET 5 /* force IRET */
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
@@ -125013,9 +194043,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/thread_info.h linux-2.6.18-xen-3.2.
#define _TIF_IA32 (1<<TIF_IA32)
#define _TIF_FORK (1<<TIF_FORK)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
-diff -rpuN linux-2.6.18.8/include/asm-x86_64/unistd.h linux-2.6.18-xen-3.2.0/include/asm-x86_64/unistd.h
---- linux-2.6.18.8/include/asm-x86_64/unistd.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/asm-x86_64/unistd.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/asm-x86_64/unistd.h linux-2.6.18-xen-3.3.0/include/asm-x86_64/unistd.h
+--- linux-2.6.18.8/include/asm-x86_64/unistd.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/asm-x86_64/unistd.h 2008-08-21 11:36:07.000000000 +0200
@@ -600,9 +600,9 @@ __SYSCALL(__NR_fchmodat, sys_fchmodat)
#define __NR_faccessat 269
__SYSCALL(__NR_faccessat, sys_faccessat)
@@ -125036,9 +194066,9 @@ diff -rpuN linux-2.6.18.8/include/asm-x86_64/unistd.h linux-2.6.18-xen-3.2.0/inc
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_COMPAT_SYS_TIME
-diff -rpuN linux-2.6.18.8/include/linux/aio.h linux-2.6.18-xen-3.2.0/include/linux/aio.h
---- linux-2.6.18.8/include/linux/aio.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/aio.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/aio.h linux-2.6.18-xen-3.3.0/include/linux/aio.h
+--- linux-2.6.18.8/include/linux/aio.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/aio.h 2008-08-21 11:36:07.000000000 +0200
@@ -191,6 +191,11 @@ struct kioctx {
struct aio_ring_info ring_info;
@@ -125051,9 +194081,9 @@ diff -rpuN linux-2.6.18.8/include/linux/aio.h linux-2.6.18-xen-3.2.0/include/lin
};
/* prototypes */
-diff -rpuN linux-2.6.18.8/include/linux/bio.h linux-2.6.18-xen-3.2.0/include/linux/bio.h
---- linux-2.6.18.8/include/linux/bio.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/bio.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/bio.h linux-2.6.18-xen-3.3.0/include/linux/bio.h
+--- linux-2.6.18.8/include/linux/bio.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/bio.h 2008-08-21 11:36:07.000000000 +0200
@@ -172,12 +172,27 @@ struct bio {
#define bio_offset(bio) bio_iovec((bio))->bv_offset
#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_idx)
@@ -125084,9 +194114,9 @@ diff -rpuN linux-2.6.18.8/include/linux/bio.h linux-2.6.18-xen-3.2.0/include/lin
/*
* will die
-diff -rpuN linux-2.6.18.8/include/linux/blkdev.h linux-2.6.18-xen-3.2.0/include/linux/blkdev.h
---- linux-2.6.18.8/include/linux/blkdev.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/blkdev.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/blkdev.h linux-2.6.18-xen-3.3.0/include/linux/blkdev.h
+--- linux-2.6.18.8/include/linux/blkdev.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/blkdev.h 2008-08-21 11:36:07.000000000 +0200
@@ -506,6 +506,8 @@ enum {
#define blk_barrier_rq(rq) ((rq)->flags & REQ_HARDBARRIER)
#define blk_fua_rq(rq) ((rq)->flags & REQ_FUA)
@@ -125096,9 +194126,9 @@ diff -rpuN linux-2.6.18.8/include/linux/blkdev.h linux-2.6.18-xen-3.2.0/include/
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
#define rq_data_dir(rq) ((rq)->flags & 1)
-diff -rpuN linux-2.6.18.8/include/linux/crash_dump.h linux-2.6.18-xen-3.2.0/include/linux/crash_dump.h
---- linux-2.6.18.8/include/linux/crash_dump.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/crash_dump.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/crash_dump.h linux-2.6.18-xen-3.3.0/include/linux/crash_dump.h
+--- linux-2.6.18.8/include/linux/crash_dump.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/crash_dump.h 2008-08-21 11:36:07.000000000 +0200
@@ -14,5 +14,13 @@ extern ssize_t copy_oldmem_page(unsigned
extern const struct file_operations proc_vmcore_operations;
extern struct proc_dir_entry *proc_vmcore;
@@ -125113,9 +194143,35 @@ diff -rpuN linux-2.6.18.8/include/linux/crash_dump.h linux-2.6.18-xen-3.2.0/incl
+
#endif /* CONFIG_CRASH_DUMP */
#endif /* LINUX_CRASHDUMP_H */
-diff -rpuN linux-2.6.18.8/include/linux/elfnote.h linux-2.6.18-xen-3.2.0/include/linux/elfnote.h
---- linux-2.6.18.8/include/linux/elfnote.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/elfnote.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/debugfs.h linux-2.6.18-xen-3.3.0/include/linux/debugfs.h
+--- linux-2.6.18.8/include/linux/debugfs.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/debugfs.h 2008-08-21 11:36:07.000000000 +0200
+@@ -41,6 +41,8 @@ struct dentry *debugfs_create_u16(const
+ struct dentry *parent, u16 *value);
+ struct dentry *debugfs_create_u32(const char *name, mode_t mode,
+ struct dentry *parent, u32 *value);
++struct dentry *debugfs_create_u64(const char *name, mode_t mode,
++ struct dentry *parent, u64 *value);
+ struct dentry *debugfs_create_bool(const char *name, mode_t mode,
+ struct dentry *parent, u32 *value);
+
+@@ -94,6 +96,13 @@ static inline struct dentry *debugfs_cre
+ return ERR_PTR(-ENODEV);
+ }
+
++static inline struct dentry *debugfs_create_u64(const char *name, mode_t mode,
++ struct dentry *parent,
++ u64 *value)
++{
++ return ERR_PTR(-ENODEV);
++}
++
+ static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *value)
+diff -rpuN linux-2.6.18.8/include/linux/elfnote.h linux-2.6.18-xen-3.3.0/include/linux/elfnote.h
+--- linux-2.6.18.8/include/linux/elfnote.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/elfnote.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,104 @@
+#ifndef _LINUX_ELFNOTE_H
+#define _LINUX_ELFNOTE_H
@@ -125221,9 +194277,9 @@ diff -rpuN linux-2.6.18.8/include/linux/elfnote.h linux-2.6.18-xen-3.2.0/include
+#endif /* __ASSEMBLER__ */
+
+#endif /* _LINUX_ELFNOTE_H */
-diff -rpuN linux-2.6.18.8/include/linux/eventpoll.h linux-2.6.18-xen-3.2.0/include/linux/eventpoll.h
---- linux-2.6.18.8/include/linux/eventpoll.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/eventpoll.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/eventpoll.h linux-2.6.18-xen-3.3.0/include/linux/eventpoll.h
+--- linux-2.6.18.8/include/linux/eventpoll.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/eventpoll.h 2008-08-21 11:36:07.000000000 +0200
@@ -90,6 +90,12 @@ static inline void eventpoll_release(str
eventpoll_release_file(file);
}
@@ -125237,9 +194293,9 @@ diff -rpuN linux-2.6.18.8/include/linux/eventpoll.h linux-2.6.18-xen-3.2.0/inclu
#else
static inline void eventpoll_init_file(struct file *file) {}
-diff -rpuN linux-2.6.18.8/include/linux/highmem.h linux-2.6.18-xen-3.2.0/include/linux/highmem.h
---- linux-2.6.18.8/include/linux/highmem.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/highmem.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/highmem.h linux-2.6.18-xen-3.3.0/include/linux/highmem.h
+--- linux-2.6.18.8/include/linux/highmem.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/highmem.h 2008-08-21 11:36:07.000000000 +0200
@@ -24,10 +24,16 @@ static inline void flush_kernel_dcache_p
/* declarations for linux/mm/highmem.c */
@@ -125257,9 +194313,9 @@ diff -rpuN linux-2.6.18.8/include/linux/highmem.h linux-2.6.18-xen-3.2.0/include
static inline void *kmap(struct page *page)
{
-diff -rpuN linux-2.6.18.8/include/linux/interrupt.h linux-2.6.18-xen-3.2.0/include/linux/interrupt.h
---- linux-2.6.18.8/include/linux/interrupt.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/interrupt.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/interrupt.h linux-2.6.18-xen-3.3.0/include/linux/interrupt.h
+--- linux-2.6.18.8/include/linux/interrupt.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/interrupt.h 2008-08-21 11:36:07.000000000 +0200
@@ -166,6 +166,12 @@ static inline int disable_irq_wake(unsig
#endif /* CONFIG_GENERIC_HARDIRQS */
@@ -125273,22 +194329,22 @@ diff -rpuN linux-2.6.18.8/include/linux/interrupt.h linux-2.6.18-xen-3.2.0/inclu
#ifndef __ARCH_SET_SOFTIRQ_PENDING
#define set_softirq_pending(x) (local_softirq_pending() = (x))
#define or_softirq_pending(x) (local_softirq_pending() |= (x))
-diff -rpuN linux-2.6.18.8/include/linux/ioport.h linux-2.6.18-xen-3.2.0/include/linux/ioport.h
---- linux-2.6.18.8/include/linux/ioport.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/ioport.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/ioport.h linux-2.6.18-xen-3.3.0/include/linux/ioport.h
+--- linux-2.6.18.8/include/linux/ioport.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/ioport.h 2008-08-21 11:36:07.000000000 +0200
@@ -93,6 +93,9 @@ struct resource_list {
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */
extern struct resource ioport_resource;
extern struct resource iomem_resource;
-+#ifdef CONFIG_XEN
++#ifdef CONFIG_PROC_IOMEM_MACHINE
+extern struct resource iomem_machine_resource;
+#endif
extern int request_resource(struct resource *root, struct resource *new);
extern struct resource * ____request_resource(struct resource *root, struct resource *new);
-diff -rpuN linux-2.6.18.8/include/linux/kexec.h linux-2.6.18-xen-3.2.0/include/linux/kexec.h
---- linux-2.6.18.8/include/linux/kexec.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/kexec.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/kexec.h linux-2.6.18-xen-3.3.0/include/linux/kexec.h
+--- linux-2.6.18.8/include/linux/kexec.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/kexec.h 2008-08-21 11:36:07.000000000 +0200
@@ -31,6 +31,13 @@
#error KEXEC_ARCH not defined
#endif
@@ -125335,20 +194391,37 @@ diff -rpuN linux-2.6.18.8/include/linux/kexec.h linux-2.6.18-xen-3.2.0/include/l
#else /* !CONFIG_KEXEC */
struct pt_regs;
struct task_struct;
-diff -rpuN linux-2.6.18.8/include/linux/mm.h linux-2.6.18-xen-3.2.0/include/linux/mm.h
---- linux-2.6.18.8/include/linux/mm.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/mm.h 2008-02-15 16:22:14.000000000 -0800
-@@ -164,6 +164,9 @@ extern unsigned int kobjsize(const void
+diff -rpuN linux-2.6.18.8/include/linux/libata.h linux-2.6.18-xen-3.3.0/include/linux/libata.h
+--- linux-2.6.18.8/include/linux/libata.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/libata.h 2008-08-21 11:36:07.000000000 +0200
+@@ -162,6 +162,12 @@ enum {
+ ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H
+ * Register FIS clearing BSY */
+ ATA_FLAG_DEBUGMSG = (1 << 13),
++ ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
++ ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
++ ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
++ ATA_FLAG_AN = (1 << 18), /* controller supports AN */
++ ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */
++ ATA_FLAG_IPM = (1 << 20), /* driver can handle IPM */
+
+ /* The following flag belongs to ap->pflags but is kept in
+ * ap->flags because it's referenced in many LLDs and will be
+diff -rpuN linux-2.6.18.8/include/linux/mm.h linux-2.6.18-xen-3.3.0/include/linux/mm.h
+--- linux-2.6.18.8/include/linux/mm.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/mm.h 2008-08-21 11:36:07.000000000 +0200
+@@ -164,6 +164,10 @@ extern unsigned int kobjsize(const void
#define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */
#define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
#define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
+#ifdef CONFIG_XEN
+#define VM_FOREIGN 0x04000000 /* Has pages belonging to another VM */
+#endif
++#define VM_ALWAYSDUMP 0x08000000 /* Always include in core dumps */
#ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
#define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
-@@ -202,6 +205,10 @@ struct vm_operations_struct {
+@@ -202,6 +206,10 @@ struct vm_operations_struct {
/* notification that a previously read-only page is about to become
* writable, if an error is returned it will cause a SIGBUS */
int (*page_mkwrite)(struct vm_area_struct *vma, struct page *page);
@@ -125359,7 +194432,7 @@ diff -rpuN linux-2.6.18.8/include/linux/mm.h linux-2.6.18-xen-3.2.0/include/linu
#ifdef CONFIG_NUMA
int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
-@@ -1027,6 +1034,13 @@ struct page *follow_page(struct vm_area_
+@@ -1027,6 +1035,13 @@ struct page *follow_page(struct vm_area_
#define FOLL_GET 0x04 /* do get_page on page */
#define FOLL_ANON 0x08 /* give ZERO_PAGE if no pgtable */
@@ -125373,9 +194446,37 @@ diff -rpuN linux-2.6.18.8/include/linux/mm.h linux-2.6.18-xen-3.2.0/include/linu
#ifdef CONFIG_PROC_FS
void vm_stat_account(struct mm_struct *, unsigned long, struct file *, long);
#else
-diff -rpuN linux-2.6.18.8/include/linux/netfilter_bridge.h linux-2.6.18-xen-3.2.0/include/linux/netfilter_bridge.h
---- linux-2.6.18.8/include/linux/netfilter_bridge.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/netfilter_bridge.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/moduleparam.h linux-2.6.18-xen-3.3.0/include/linux/moduleparam.h
+--- linux-2.6.18.8/include/linux/moduleparam.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/moduleparam.h 2008-08-21 11:36:07.000000000 +0200
+@@ -58,13 +58,23 @@ struct kparam_array
+ void *elem;
+ };
+
++/* On alpha, ia64 and ppc64 relocations to global data cannot go into
++ read-only sections (which is part of respective UNIX ABI on these
++ platforms). So 'const' makes no sense and even causes compile failures
++ with some compilers. */
++#if defined(CONFIG_ALPHA) || defined(CONFIG_IA64) || defined(CONFIG_PPC64)
++#define __moduleparam_const
++#else
++#define __moduleparam_const const
++#endif
++
+ /* This is the fundamental function for registering boot/module
+ parameters. perm sets the visibility in driverfs: 000 means it's
+ not there, read bits mean it's readable, write bits mean it's
+ writable. */
+ #define __module_param_call(prefix, name, set, get, arg, perm) \
+ static char __param_str_##name[] = prefix #name; \
+- static struct kernel_param const __param_##name \
++ static struct kernel_param __moduleparam_const __param_##name \
+ __attribute_used__ \
+ __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
+ = { __param_str_##name, perm, set, get, arg }
+diff -rpuN linux-2.6.18.8/include/linux/netfilter_bridge.h linux-2.6.18-xen-3.3.0/include/linux/netfilter_bridge.h
+--- linux-2.6.18.8/include/linux/netfilter_bridge.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/netfilter_bridge.h 2008-08-21 11:36:07.000000000 +0200
@@ -7,6 +7,7 @@
#include <linux/netfilter.h>
#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
@@ -125409,9 +194510,9 @@ diff -rpuN linux-2.6.18.8/include/linux/netfilter_bridge.h linux-2.6.18-xen-3.2.
}
}
return 0;
-diff -rpuN linux-2.6.18.8/include/linux/oprofile.h linux-2.6.18-xen-3.2.0/include/linux/oprofile.h
---- linux-2.6.18.8/include/linux/oprofile.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/oprofile.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/oprofile.h linux-2.6.18-xen-3.3.0/include/linux/oprofile.h
+--- linux-2.6.18.8/include/linux/oprofile.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/oprofile.h 2008-08-21 11:36:07.000000000 +0200
@@ -16,6 +16,8 @@
#include <linux/types.h>
#include <linux/spinlock.h>
@@ -125442,9 +194543,9 @@ diff -rpuN linux-2.6.18.8/include/linux/oprofile.h linux-2.6.18-xen-3.2.0/includ
/**
* Create a file of the given name as a child of the given root, with
-diff -rpuN linux-2.6.18.8/include/linux/page-flags.h linux-2.6.18-xen-3.2.0/include/linux/page-flags.h
---- linux-2.6.18.8/include/linux/page-flags.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/page-flags.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/page-flags.h linux-2.6.18-xen-3.3.0/include/linux/page-flags.h
+--- linux-2.6.18.8/include/linux/page-flags.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/page-flags.h 2008-08-21 11:36:07.000000000 +0200
@@ -98,6 +98,8 @@
#define PG_uncached 31 /* Page has been mapped as uncached */
#endif
@@ -125454,29 +194555,83 @@ diff -rpuN linux-2.6.18.8/include/linux/page-flags.h linux-2.6.18-xen-3.2.0/incl
/*
* Manipulation of page state flags
*/
-@@ -247,6 +249,18 @@
+@@ -247,6 +249,19 @@
#define SetPageUncached(page) set_bit(PG_uncached, &(page)->flags)
#define ClearPageUncached(page) clear_bit(PG_uncached, &(page)->flags)
+#define PageForeign(page) test_bit(PG_foreign, &(page)->flags)
-+#define SetPageForeign(page, dtor) do { \
-+ set_bit(PG_foreign, &(page)->flags); \
-+ (page)->index = (long)(dtor); \
++#define SetPageForeign(_page, dtor) do { \
++ set_bit(PG_foreign, &(_page)->flags); \
++ BUG_ON((dtor) == (void (*)(struct page *))0); \
++ (_page)->index = (long)(dtor); \
+} while (0)
-+#define ClearPageForeign(page) do { \
-+ clear_bit(PG_foreign, &(page)->flags); \
-+ (page)->index = 0; \
++#define ClearPageForeign(page) do { \
++ clear_bit(PG_foreign, &(page)->flags); \
++ (page)->index = 0; \
+} while (0)
-+#define PageForeignDestructor(page) \
-+ ( (void (*) (struct page *)) (page)->index )(page)
++#define PageForeignDestructor(_page) \
++ ((void (*)(struct page *))(_page)->index)(_page)
+
struct page; /* forward declaration */
int test_clear_page_dirty(struct page *page);
-diff -rpuN linux-2.6.18.8/include/linux/pci_ids.h linux-2.6.18-xen-3.2.0/include/linux/pci_ids.h
---- linux-2.6.18.8/include/linux/pci_ids.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/pci_ids.h 2008-02-15 16:22:14.000000000 -0800
-@@ -2188,6 +2188,13 @@
+diff -rpuN linux-2.6.18.8/include/linux/pci.h linux-2.6.18-xen-3.3.0/include/linux/pci.h
+--- linux-2.6.18.8/include/linux/pci.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/pci.h 2008-08-21 11:36:07.000000000 +0200
+@@ -152,6 +152,9 @@ struct pci_dev {
+ * directly, use the values stored here. They might be different!
+ */
+ unsigned int irq;
++#ifdef CONFIG_XEN
++ unsigned int irq_old;
++#endif
+ struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
+
+ /* These fields are used by common fixups */
+@@ -596,6 +599,10 @@ static inline int pci_enable_msix(struct
+ struct msix_entry *entries, int nvec) {return -1;}
+ static inline void pci_disable_msix(struct pci_dev *dev) {}
+ static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
++#ifdef CONFIG_XEN
++#define register_msi_get_owner(func) 0
++#define unregister_msi_get_owner(func) 0
++#endif
+ #else
+ extern void pci_scan_msi_device(struct pci_dev *dev);
+ extern int pci_enable_msi(struct pci_dev *dev);
+@@ -604,6 +611,10 @@ extern int pci_enable_msix(struct pci_de
+ struct msix_entry *entries, int nvec);
+ extern void pci_disable_msix(struct pci_dev *dev);
+ extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
++#ifdef CONFIG_XEN
++extern int register_msi_get_owner(int (*func)(struct pci_dev *dev));
++extern int unregister_msi_get_owner(int (*func)(struct pci_dev *dev));
++#endif
+ #endif
+
+ extern void pci_block_user_cfg_access(struct pci_dev *dev);
+diff -rpuN linux-2.6.18.8/include/linux/pci_ids.h linux-2.6.18-xen-3.3.0/include/linux/pci_ids.h
+--- linux-2.6.18.8/include/linux/pci_ids.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/pci_ids.h 2008-08-21 11:36:07.000000000 +0200
+@@ -15,6 +15,8 @@
+ #define PCI_CLASS_STORAGE_FLOPPY 0x0102
+ #define PCI_CLASS_STORAGE_IPI 0x0103
+ #define PCI_CLASS_STORAGE_RAID 0x0104
++#define PCI_CLASS_STORAGE_SATA 0x0106
++#define PCI_CLASS_STORAGE_SATA_AHCI 0x010601
+ #define PCI_CLASS_STORAGE_SAS 0x0107
+ #define PCI_CLASS_STORAGE_OTHER 0x0180
+
+@@ -363,6 +365,8 @@
+ #define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380
+ #define PCI_DEVICE_ID_ATI_IXP600_SRAID 0x4381
+ #define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c
++#define PCI_DEVICE_ID_ATI_IXP700_SATA 0x4390
++#define PCI_DEVICE_ID_ATI_IXP700_IDE 0x439c
+
+ #define PCI_VENDOR_ID_VLSI 0x1004
+ #define PCI_DEVICE_ID_VLSI_82C592 0x0005
+@@ -2188,6 +2192,13 @@
#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815
#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e
#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850
@@ -125490,9 +194645,22 @@ diff -rpuN linux-2.6.18.8/include/linux/pci_ids.h linux-2.6.18-xen-3.2.0/include
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575
#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
-diff -rpuN linux-2.6.18.8/include/linux/sched.h linux-2.6.18-xen-3.2.0/include/linux/sched.h
---- linux-2.6.18.8/include/linux/sched.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/sched.h 2008-02-15 16:22:14.000000000 -0800
+@@ -2202,6 +2213,12 @@
+ #define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599
+ #define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a
+ #define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
++#define PCI_DEVICE_ID_INTEL_ICH10_0 0x3a14
++#define PCI_DEVICE_ID_INTEL_ICH10_1 0x3a16
++#define PCI_DEVICE_ID_INTEL_ICH10_2 0x3a18
++#define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a
++#define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30
++#define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60
+ #define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
+ #define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
+ #define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020
+diff -rpuN linux-2.6.18.8/include/linux/sched.h linux-2.6.18-xen-3.3.0/include/linux/sched.h
+--- linux-2.6.18.8/include/linux/sched.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/sched.h 2008-08-21 11:36:07.000000000 +0200
@@ -211,10 +211,15 @@ extern void update_process_times(int use
extern void scheduler_tick(void);
@@ -125509,9 +194677,9 @@ diff -rpuN linux-2.6.18.8/include/linux/sched.h linux-2.6.18-xen-3.2.0/include/l
static inline void softlockup_tick(void)
{
}
-diff -rpuN linux-2.6.18.8/include/linux/skbuff.h linux-2.6.18-xen-3.2.0/include/linux/skbuff.h
---- linux-2.6.18.8/include/linux/skbuff.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/skbuff.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/skbuff.h linux-2.6.18-xen-3.3.0/include/linux/skbuff.h
+--- linux-2.6.18.8/include/linux/skbuff.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/skbuff.h 2008-08-21 11:36:07.000000000 +0200
@@ -203,6 +203,8 @@ enum {
* @local_df: allow local fragmentation
* @cloned: Head may be cloned (check refcnt to be sure)
@@ -125535,9 +194703,9 @@ diff -rpuN linux-2.6.18.8/include/linux/skbuff.h linux-2.6.18-xen-3.2.0/include/
__be16 protocol;
void (*destructor)(struct sk_buff *skb);
-diff -rpuN linux-2.6.18.8/include/linux/sysctl.h linux-2.6.18-xen-3.2.0/include/linux/sysctl.h
---- linux-2.6.18.8/include/linux/sysctl.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/sysctl.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/sysctl.h linux-2.6.18-xen-3.3.0/include/linux/sysctl.h
+--- linux-2.6.18.8/include/linux/sysctl.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/sysctl.h 2008-08-21 11:36:07.000000000 +0200
@@ -6,10 +6,17 @@
****************************************************************
****************************************************************
@@ -125567,9 +194735,9 @@ diff -rpuN linux-2.6.18.8/include/linux/sysctl.h linux-2.6.18-xen-3.2.0/include/
#endif
enum
-diff -rpuN linux-2.6.18.8/include/linux/vermagic.h linux-2.6.18-xen-3.2.0/include/linux/vermagic.h
---- linux-2.6.18.8/include/linux/vermagic.h 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/linux/vermagic.h 2008-02-15 16:22:14.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/linux/vermagic.h linux-2.6.18-xen-3.3.0/include/linux/vermagic.h
+--- linux-2.6.18.8/include/linux/vermagic.h 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/linux/vermagic.h 2008-08-21 11:36:07.000000000 +0200
@@ -17,6 +17,11 @@
#else
#define MODULE_VERMAGIC_MODULE_UNLOAD ""
@@ -125590,9 +194758,9 @@ diff -rpuN linux-2.6.18.8/include/linux/vermagic.h linux-2.6.18-xen-3.2.0/includ
+ MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_XEN \
+ MODULE_ARCH_VERMAGIC \
"gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
-diff -rpuN linux-2.6.18.8/include/xen/balloon.h linux-2.6.18-xen-3.2.0/include/xen/balloon.h
---- linux-2.6.18.8/include/xen/balloon.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/balloon.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/balloon.h linux-2.6.18-xen-3.3.0/include/xen/balloon.h
+--- linux-2.6.18.8/include/xen/balloon.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/balloon.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * balloon.h
@@ -125651,10 +194819,30 @@ diff -rpuN linux-2.6.18.8/include/xen/balloon.h linux-2.6.18-xen-3.2.0/include/x
+#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags)
+
+#endif /* __ASM_BALLOON_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/blkif.h linux-2.6.18-xen-3.2.0/include/xen/blkif.h
---- linux-2.6.18.8/include/xen/blkif.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/blkif.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,101 @@
+diff -rpuN linux-2.6.18.8/include/xen/blkif.h linux-2.6.18-xen-3.3.0/include/xen/blkif.h
+--- linux-2.6.18.8/include/xen/blkif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/blkif.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,123 @@
++/*
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
+#ifndef __XEN_BLKIF_H__
+#define __XEN_BLKIF_H__
+
@@ -125735,8 +194923,9 @@ diff -rpuN linux-2.6.18.8/include/xen/blkif.h linux-2.6.18-xen-3.2.0/include/xen
+ dst->handle = src->handle;
+ dst->id = src->id;
+ dst->sector_number = src->sector_number;
-+ if (n > src->nr_segments)
-+ n = src->nr_segments;
++ barrier();
++ if (n > dst->nr_segments)
++ n = dst->nr_segments;
+ for (i = 0; i < n; i++)
+ dst->seg[i] = src->seg[i];
+}
@@ -125749,16 +194938,17 @@ diff -rpuN linux-2.6.18.8/include/xen/blkif.h linux-2.6.18-xen-3.2.0/include/xen
+ dst->handle = src->handle;
+ dst->id = src->id;
+ dst->sector_number = src->sector_number;
-+ if (n > src->nr_segments)
-+ n = src->nr_segments;
++ barrier();
++ if (n > dst->nr_segments)
++ n = dst->nr_segments;
+ for (i = 0; i < n; i++)
+ dst->seg[i] = src->seg[i];
+}
+
+#endif /* __XEN_BLKIF_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/compat_ioctl.h linux-2.6.18-xen-3.2.0/include/xen/compat_ioctl.h
---- linux-2.6.18.8/include/xen/compat_ioctl.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/compat_ioctl.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/compat_ioctl.h linux-2.6.18-xen-3.3.0/include/xen/compat_ioctl.h
+--- linux-2.6.18.8/include/xen/compat_ioctl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/compat_ioctl.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,45 @@
+/*
+ * This program is free software; you can redistribute it and/or
@@ -125805,9 +194995,9 @@ diff -rpuN linux-2.6.18.8/include/xen/compat_ioctl.h linux-2.6.18-xen-3.2.0/incl
+ _IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch_32))
+
+#endif /* __LINUX_XEN_COMPAT_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/cpu_hotplug.h linux-2.6.18-xen-3.2.0/include/xen/cpu_hotplug.h
---- linux-2.6.18.8/include/xen/cpu_hotplug.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/cpu_hotplug.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/cpu_hotplug.h linux-2.6.18-xen-3.3.0/include/xen/cpu_hotplug.h
+--- linux-2.6.18.8/include/xen/cpu_hotplug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/cpu_hotplug.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,41 @@
+#ifndef __XEN_CPU_HOTPLUG_H__
+#define __XEN_CPU_HOTPLUG_H__
@@ -125850,9 +195040,9 @@ diff -rpuN linux-2.6.18.8/include/xen/cpu_hotplug.h linux-2.6.18-xen-3.2.0/inclu
+#endif /* !defined(CONFIG_HOTPLUG_CPU) */
+
+#endif /* __XEN_CPU_HOTPLUG_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/driver_util.h linux-2.6.18-xen-3.2.0/include/xen/driver_util.h
---- linux-2.6.18.8/include/xen/driver_util.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/driver_util.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/driver_util.h linux-2.6.18-xen-3.3.0/include/xen/driver_util.h
+--- linux-2.6.18.8/include/xen/driver_util.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/driver_util.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,14 @@
+
+#ifndef __ASM_XEN_DRIVER_UTIL_H__
@@ -125868,10 +195058,10 @@ diff -rpuN linux-2.6.18.8/include/xen/driver_util.h linux-2.6.18-xen-3.2.0/inclu
+extern struct class *get_xen_class(void);
+
+#endif /* __ASM_XEN_DRIVER_UTIL_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/evtchn.h linux-2.6.18-xen-3.2.0/include/xen/evtchn.h
---- linux-2.6.18.8/include/xen/evtchn.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/evtchn.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,139 @@
+diff -rpuN linux-2.6.18.8/include/xen/evtchn.h linux-2.6.18-xen-3.3.0/include/xen/evtchn.h
+--- linux-2.6.18.8/include/xen/evtchn.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/evtchn.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,153 @@
+/******************************************************************************
+ * evtchn.h
+ *
@@ -126010,10 +195200,24 @@ diff -rpuN linux-2.6.18.8/include/xen/evtchn.h linux-2.6.18-xen-3.2.0/include/xe
+void notify_remote_via_irq(int irq);
+int irq_to_evtchn_port(int irq);
+
++#define PIRQ_SET_MAPPING 0x0
++#define PIRQ_CLEAR_MAPPING 0x1
++#define PIRQ_GET_MAPPING 0x3
++int pirq_mapstatus(int pirq, int action);
++int set_pirq_hw_action(int pirq, int (*action)(int pirq, int action));
++int clear_pirq_hw_action(int pirq);
++
++#define PIRQ_STARTUP 1
++#define PIRQ_SHUTDOWN 2
++#define PIRQ_ENABLE 3
++#define PIRQ_DISABLE 4
++#define PIRQ_END 5
++#define PIRQ_ACK 6
++
+#endif /* __ASM_EVTCHN_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/features.h linux-2.6.18-xen-3.2.0/include/xen/features.h
---- linux-2.6.18.8/include/xen/features.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/features.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/features.h linux-2.6.18-xen-3.3.0/include/xen/features.h
+--- linux-2.6.18.8/include/xen/features.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/features.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * features.h
@@ -126035,9 +195239,9 @@ diff -rpuN linux-2.6.18.8/include/xen/features.h linux-2.6.18-xen-3.2.0/include/
+#define xen_feature(flag) (xen_features[flag])
+
+#endif /* __ASM_XEN_FEATURES_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/firmware.h linux-2.6.18-xen-3.2.0/include/xen/firmware.h
---- linux-2.6.18.8/include/xen/firmware.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/firmware.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/firmware.h linux-2.6.18-xen-3.3.0/include/xen/firmware.h
+--- linux-2.6.18.8/include/xen/firmware.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/firmware.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,10 @@
+#ifndef __XEN_FIRMWARE_H__
+#define __XEN_FIRMWARE_H__
@@ -126049,9 +195253,9 @@ diff -rpuN linux-2.6.18.8/include/xen/firmware.h linux-2.6.18-xen-3.2.0/include/
+void copy_edid(void);
+
+#endif /* __XEN_FIRMWARE_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/gnttab.h linux-2.6.18-xen-3.2.0/include/xen/gnttab.h
---- linux-2.6.18.8/include/xen/gnttab.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/gnttab.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/gnttab.h linux-2.6.18-xen-3.3.0/include/xen/gnttab.h
+--- linux-2.6.18.8/include/xen/gnttab.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/gnttab.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,163 @@
+/******************************************************************************
+ * gnttab.h
@@ -126216,9 +195420,9 @@ diff -rpuN linux-2.6.18.8/include/xen/gnttab.h linux-2.6.18-xen-3.2.0/include/xe
+}
+
+#endif /* __ASM_GNTTAB_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/hvm.h linux-2.6.18-xen-3.2.0/include/xen/hvm.h
---- linux-2.6.18.8/include/xen/hvm.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/hvm.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/hvm.h linux-2.6.18-xen-3.3.0/include/xen/hvm.h
+--- linux-2.6.18.8/include/xen/hvm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/hvm.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,23 @@
+/* Simple wrappers around HVM functions */
+#ifndef XEN_HVM_H__
@@ -126243,9 +195447,9 @@ diff -rpuN linux-2.6.18.8/include/xen/hvm.h linux-2.6.18-xen-3.2.0/include/xen/h
+}
+
+#endif /* XEN_HVM_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/hypercall.h linux-2.6.18-xen-3.2.0/include/xen/hypercall.h
---- linux-2.6.18.8/include/xen/hypercall.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/hypercall.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/hypercall.h linux-2.6.18-xen-3.3.0/include/xen/hypercall.h
+--- linux-2.6.18.8/include/xen/hypercall.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/hypercall.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,30 @@
+#ifndef __XEN_HYPERCALL_H__
+#define __XEN_HYPERCALL_H__
@@ -126277,9 +195481,9 @@ diff -rpuN linux-2.6.18.8/include/xen/hypercall.h linux-2.6.18-xen-3.2.0/include
+#define VOID(expr) ((void)((expr)?:0))
+
+#endif /* __XEN_HYPERCALL_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/hypervisor_sysfs.h linux-2.6.18-xen-3.2.0/include/xen/hypervisor_sysfs.h
---- linux-2.6.18.8/include/xen/hypervisor_sysfs.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/hypervisor_sysfs.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/hypervisor_sysfs.h linux-2.6.18-xen-3.3.0/include/xen/hypervisor_sysfs.h
+--- linux-2.6.18.8/include/xen/hypervisor_sysfs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/hypervisor_sysfs.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,30 @@
+/*
+ * copyright (c) 2006 IBM Corporation
@@ -126311,51 +195515,9 @@ diff -rpuN linux-2.6.18.8/include/xen/hypervisor_sysfs.h linux-2.6.18-xen-3.2.0/
+};
+
+#endif /* _HYP_SYSFS_H_ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/COPYING linux-2.6.18-xen-3.2.0/include/xen/interface/COPYING
---- linux-2.6.18.8/include/xen/interface/COPYING 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/COPYING 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,38 @@
-+XEN NOTICE
-+==========
-+
-+This copyright applies to all files within this subdirectory and its
-+subdirectories:
-+ include/public/*.h
-+ include/public/hvm/*.h
-+ include/public/io/*.h
-+
-+The intention is that these files can be freely copied into the source
-+tree of an operating system when porting that OS to run on Xen. Doing
-+so does *not* cause the OS to become subject to the terms of the GPL.
-+
-+All other files in the Xen source distribution are covered by version
-+2 of the GNU General Public License except where explicitly stated
-+otherwise within individual source files.
-+
-+ -- Keir Fraser (on behalf of the Xen team)
-+
-+=====================================================================
-+
-+Permission is hereby granted, free of charge, to any person obtaining a copy
-+of this software and associated documentation files (the "Software"), to
-+deal in the Software without restriction, including without limitation the
-+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-+sell copies of the Software, and to permit persons to whom the Software is
-+furnished to do so, subject to the following conditions:
-+
-+The above copyright notice and this permission notice shall be included in
-+all copies or substantial portions of the Software.
-+
-+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+DEALINGS IN THE SOFTWARE.
-diff -rpuN linux-2.6.18.8/include/xen/interface/acm.h linux-2.6.18-xen-3.2.0/include/xen/interface/acm.h
---- linux-2.6.18.8/include/xen/interface/acm.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/acm.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/acm.h linux-2.6.18-xen-3.3.0/include/xen/interface/acm.h
+--- linux-2.6.18.8/include/xen/interface/acm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/acm.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,228 @@
+/*
+ * acm.h: Xen access control module interface defintions
@@ -126585,9 +195747,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/acm.h linux-2.6.18-xen-3.2.0/inc
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/acm_ops.h linux-2.6.18-xen-3.2.0/include/xen/interface/acm_ops.h
---- linux-2.6.18.8/include/xen/interface/acm_ops.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/acm_ops.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/acm_ops.h linux-2.6.18-xen-3.3.0/include/xen/interface/acm_ops.h
+--- linux-2.6.18.8/include/xen/interface/acm_ops.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/acm_ops.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,159 @@
+/*
+ * acm_ops.h: Xen access control module hypervisor commands
@@ -126748,9 +195910,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/acm_ops.h linux-2.6.18-xen-3.2.0
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64/debug_op.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-ia64/debug_op.h
---- linux-2.6.18.8/include/xen/interface/arch-ia64/debug_op.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-ia64/debug_op.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64/debug_op.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64/debug_op.h
+--- linux-2.6.18.8/include/xen/interface/arch-ia64/debug_op.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64/debug_op.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,96 @@
+/******************************************************************************
+ * debug_op.h
@@ -126848,9 +196010,101 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64/debug_op.h linux-2.6.1
+DEFINE_XEN_GUEST_HANDLE(xen_ia64_debug_op_t);
+
+#endif /* __XEN_PUBLIC_IA64_DEBUG_OP_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64/hvm/save.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-ia64/hvm/save.h
---- linux-2.6.18.8/include/xen/interface/arch-ia64/hvm/save.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-ia64/hvm/save.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64/hvm/memmap.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64/hvm/memmap.h
+--- linux-2.6.18.8/include/xen/interface/arch-ia64/hvm/memmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64/hvm/memmap.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,88 @@
++/******************************************************************************
++ * memmap.h
++ *
++ * Copyright (c) 2008 Tristan Gingold <tgingold AT free fr>
++ *
++ * 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; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#ifndef __XEN_PUBLIC_HVM_MEMMAP_IA64_H__
++#define __XEN_PUBLIC_HVM_MEMMAP_IA64_H__
++
++#define MEM_G (1UL << 30)
++#define MEM_M (1UL << 20)
++#define MEM_K (1UL << 10)
++
++/* Guest physical address of IO ports space. */
++#define MMIO_START (3 * MEM_G)
++#define MMIO_SIZE (512 * MEM_M)
++
++#define VGA_IO_START 0xA0000UL
++#define VGA_IO_SIZE 0x20000
++
++#define LEGACY_IO_START (MMIO_START + MMIO_SIZE)
++#define LEGACY_IO_SIZE (64 * MEM_M)
++
++#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE)
++#define IO_PAGE_SIZE XEN_PAGE_SIZE
++
++#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE)
++#define STORE_PAGE_SIZE XEN_PAGE_SIZE
++
++#define BUFFER_IO_PAGE_START (STORE_PAGE_START + STORE_PAGE_SIZE)
++#define BUFFER_IO_PAGE_SIZE XEN_PAGE_SIZE
++
++#define BUFFER_PIO_PAGE_START (BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE)
++#define BUFFER_PIO_PAGE_SIZE XEN_PAGE_SIZE
++
++#define IO_SAPIC_START 0xfec00000UL
++#define IO_SAPIC_SIZE 0x100000
++
++#define PIB_START 0xfee00000UL
++#define PIB_SIZE 0x200000
++
++#define GFW_START (4 * MEM_G - 16 * MEM_M)
++#define GFW_SIZE (16 * MEM_M)
++
++/* domVTI */
++#define GPFN_FRAME_BUFFER 0x1 /* VGA framebuffer */
++#define GPFN_LOW_MMIO 0x2 /* Low MMIO range */
++#define GPFN_PIB 0x3 /* PIB base */
++#define GPFN_IOSAPIC 0x4 /* IOSAPIC base */
++#define GPFN_LEGACY_IO 0x5 /* Legacy I/O base */
++#define GPFN_HIGH_MMIO 0x6 /* High MMIO range */
++
++/* Nvram belongs to GFW memory space */
++#define NVRAM_SIZE (MEM_K * 64)
++#define NVRAM_START (GFW_START + 10 * MEM_M)
++
++#define NVRAM_VALID_SIG 0x4650494e45584948 /* "HIXENIPF" */
++struct nvram_save_addr {
++ unsigned long addr;
++ unsigned long signature;
++};
++
++#endif /* __XEN_PUBLIC_HVM_MEMMAP_IA64_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64/hvm/save.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64/hvm/save.h
+--- linux-2.6.18.8/include/xen/interface/arch-ia64/hvm/save.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64/hvm/save.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,201 @@
+/******************************************************************************
+ * save_types.h
@@ -127053,10 +196307,103 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64/hvm/save.h linux-2.6.1
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-ia64.h
---- linux-2.6.18.8/include/xen/interface/arch-ia64.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-ia64.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,651 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64/sioemu.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64/sioemu.h
+--- linux-2.6.18.8/include/xen/interface/arch-ia64/sioemu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64/sioemu.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,89 @@
++/******************************************************************************
++ * sioemu.h
++ *
++ * Copyright (c) 2008 Tristan Gingold <tgingold@free.fr>
++ *
++ * 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; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#ifndef __XEN_PUBLIC_IA64_SIOEMU_H__
++#define __XEN_PUBLIC_IA64_SIOEMU_H__
++
++/* SIOEMU specific hypercalls.
++ The numbers are the minor part of FW_HYPERCALL_SIOEMU. */
++
++/* Defines the callback entry point. r8=ip, r9=data.
++ Must be called per-vcpu. */
++#define SIOEMU_HYPERCALL_SET_CALLBACK 0x01
++
++/* Finish sioemu fw initialization and start firmware. r8=ip. */
++#define SIOEMU_HYPERCALL_START_FW 0x02
++
++/* Add IO pages in physmap. */
++#define SIOEMU_HYPERCALL_ADD_IO_PHYSMAP 0x03
++
++/* Get wallclock time. */
++#define SIOEMU_HYPERCALL_GET_TIME 0x04
++
++/* Flush cache. */
++#define SIOEMU_HYPERCALL_FLUSH_CACHE 0x07
++
++/* Get freq base. */
++#define SIOEMU_HYPERCALL_FREQ_BASE 0x08
++
++/* Return from callback. */
++#define SIOEMU_HYPERCALL_CALLBACK_RETURN 0x09
++
++/* Deliver an interrupt. */
++#define SIOEMU_HYPERCALL_DELIVER_INT 0x0a
++
++/* SIOEMU callback reason. */
++
++/* An event (from event channel) has to be delivered. */
++#define SIOEMU_CB_EVENT 0x00
++
++/* Emulate an IO access. */
++#define SIOEMU_CB_IO_EMULATE 0x01
++
++/* An IPI is sent to a dead vcpu. */
++#define SIOEMU_CB_WAKEUP_VCPU 0x02
++
++/* A SAL hypercall is executed. */
++#define SIOEMU_CB_SAL_ASSIST 0x03
++
++#ifndef __ASSEMBLY__
++struct sioemu_callback_info {
++ /* Saved registers. */
++ unsigned long ip;
++ unsigned long psr;
++ unsigned long ifs;
++ unsigned long nats;
++ unsigned long r8;
++ unsigned long r9;
++ unsigned long r10;
++ unsigned long r11;
++
++ /* Callback parameters. */
++ unsigned long cause;
++ unsigned long arg0;
++ unsigned long arg1;
++ unsigned long arg2;
++ unsigned long arg3;
++ unsigned long _pad2[2];
++ unsigned long r2;
++};
++#endif /* __ASSEMBLY__ */
++#endif /* __XEN_PUBLIC_IA64_SIOEMU_H__ */
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64.h
+--- linux-2.6.18.8/include/xen/interface/arch-ia64.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-ia64.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,621 @@
+/******************************************************************************
+ * arch-ia64/hypervisor-if.h
+ *
@@ -127082,9 +196429,15 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.2
+ *
+ */
+
++#include "xen.h"
++
+#ifndef __HYPERVISOR_IF_IA64_H__
+#define __HYPERVISOR_IF_IA64_H__
+
++#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
++#error "Anonymous structs/unions are a GNU extension."
++#endif
++
+/* Structural guest handles introduced in 0x00030201. */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030201
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
@@ -127121,6 +196474,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.2
+/* WARNING: before changing this, check that shared_info fits on a page */
+#define MAX_VIRT_CPUS 64
+
++/* IO ports location for PV. */
++#define IO_PORTS_PADDR 0x00000ffffc000000UL
++#define IO_PORTS_SIZE 0x0000000004000000UL
++
+#ifndef __ASSEMBLY__
+
+typedef unsigned long xen_ulong_t;
@@ -127133,54 +196490,6 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.2
+
+#define INVALID_MFN (~0UL)
+
-+#define MEM_G (1UL << 30)
-+#define MEM_M (1UL << 20)
-+#define MEM_K (1UL << 10)
-+
-+/* Guest physical address of IO ports space. */
-+#define IO_PORTS_PADDR 0x00000ffffc000000UL
-+#define IO_PORTS_SIZE 0x0000000004000000UL
-+
-+#define MMIO_START (3 * MEM_G)
-+#define MMIO_SIZE (512 * MEM_M)
-+
-+#define VGA_IO_START 0xA0000UL
-+#define VGA_IO_SIZE 0x20000
-+
-+#define LEGACY_IO_START (MMIO_START + MMIO_SIZE)
-+#define LEGACY_IO_SIZE (64*MEM_M)
-+
-+#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE)
-+#define IO_PAGE_SIZE XEN_PAGE_SIZE
-+
-+#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE)
-+#define STORE_PAGE_SIZE XEN_PAGE_SIZE
-+
-+#define BUFFER_IO_PAGE_START (STORE_PAGE_START + STORE_PAGE_SIZE)
-+#define BUFFER_IO_PAGE_SIZE XEN_PAGE_SIZE
-+
-+#define BUFFER_PIO_PAGE_START (BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE)
-+#define BUFFER_PIO_PAGE_SIZE XEN_PAGE_SIZE
-+
-+#define IO_SAPIC_START 0xfec00000UL
-+#define IO_SAPIC_SIZE 0x100000
-+
-+#define PIB_START 0xfee00000UL
-+#define PIB_SIZE 0x200000
-+
-+#define GFW_START (4*MEM_G -16*MEM_M)
-+#define GFW_SIZE (16*MEM_M)
-+
-+/* Nvram belongs to GFW memory space */
-+#define NVRAM_SIZE (MEM_K * 64)
-+#define NVRAM_START (GFW_START + 10 * MEM_M)
-+
-+#define NVRAM_VALID_SIG 0x4650494e45584948 // "HIXENIPF"
-+struct nvram_save_addr {
-+ unsigned long addr;
-+ unsigned long signature;
-+};
-+
+struct pt_fpreg {
+ union {
+ unsigned long bits[2];
@@ -127488,6 +196797,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.2
+struct vcpu_guest_context {
+#define VGCF_EXTRA_REGS (1UL << 1) /* Set extra regs. */
+#define VGCF_SET_CR_IRR (1UL << 2) /* Set cr_irr[0:3]. */
++#define VGCF_online (1UL << 3) /* make this vcpu online */
+ unsigned long flags; /* VGCF_* flags */
+
+ struct vcpu_guest_context_regs regs;
@@ -127562,6 +196872,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.2
+/* Internal only: associated with PGC_allocated bit */
+#define _ASSIGN_pgc_allocated 3
+#define ASSIGN_pgc_allocated (1UL << _ASSIGN_pgc_allocated)
++/* Page is an IO page. */
++#define _ASSIGN_io 4
++#define ASSIGN_io (1UL << _ASSIGN_io)
+
+/* This structure has the same layout of struct ia64_boot_param, defined in
+ <asm/system.h>. It is redefined here to ease use. */
@@ -127697,6 +197010,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.2
+#endif /* __ASSEMBLY__ */
+#endif /* XEN */
+
++#ifndef __ASSEMBLY__
++#include "arch-ia64/hvm/memmap.h"
++#endif
++
+#endif /* __HYPERVISOR_IF_IA64_H__ */
+
+/*
@@ -127708,10 +197025,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-ia64.h linux-2.6.18-xen-3.2
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-powerpc.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-powerpc.h
---- linux-2.6.18.8/include/xen/interface/arch-powerpc.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-powerpc.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,118 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-powerpc.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-powerpc.h
+--- linux-2.6.18.8/include/xen/interface/arch-powerpc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-powerpc.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,120 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
@@ -127736,6 +197053,8 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-powerpc.h linux-2.6.18-xen-
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
++#include "xen.h"
++
+#ifndef __XEN_PUBLIC_ARCH_PPC_64_H__
+#define __XEN_PUBLIC_ARCH_PPC_64_H__
+
@@ -127830,9 +197149,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-powerpc.h linux-2.6.18-xen-
+#endif
+
+#endif
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/cpuid.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/cpuid.h
---- linux-2.6.18.8/include/xen/interface/arch-x86/cpuid.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/cpuid.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/cpuid.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/cpuid.h
+--- linux-2.6.18.8/include/xen/interface/arch-x86/cpuid.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/cpuid.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,68 @@
+/******************************************************************************
+ * arch-x86/cpuid.h
@@ -127902,10 +197221,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/cpuid.h linux-2.6.18-xe
+#define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0)
+
+#endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/hvm/save.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/hvm/save.h
---- linux-2.6.18.8/include/xen/interface/arch-x86/hvm/save.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/hvm/save.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,430 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/hvm/save.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/hvm/save.h
+--- linux-2.6.18.8/include/xen/interface/arch-x86/hvm/save.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/hvm/save.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,429 @@
+/*
+ * Structure definitions for HVM state that is held by Xen and must
+ * be saved along with the domain's memory and device-model state.
@@ -128179,8 +197498,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/hvm/save.h linux-2.6.18
+DECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
+
+struct hvm_hw_lapic_regs {
-+ /* A 4k page of register state */
-+ uint8_t data[0x400];
++ uint8_t data[1024];
+};
+
+DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
@@ -128336,10 +197654,501 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/hvm/save.h linux-2.6.18
+#define HVM_SAVE_CODE_MAX 14
+
+#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_32.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/xen-x86_32.h
---- linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_32.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/xen-x86_32.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,185 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/xen.h
+--- linux-2.6.18.8/include/xen/interface/arch-x86/xen.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/xen.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,204 @@
++/******************************************************************************
++ * arch-x86/xen.h
++ *
++ * Guest OS interface to x86 Xen.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Copyright (c) 2004-2006, K A Fraser
++ */
++
++#include "../xen.h"
++
++#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
++#define __XEN_PUBLIC_ARCH_X86_XEN_H__
++
++/* Structural guest handles introduced in 0x00030201. */
++#if __XEN_INTERFACE_VERSION__ >= 0x00030201
++#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
++ typedef struct { type *p; } __guest_handle_ ## name
++#else
++#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
++ typedef type * __guest_handle_ ## name
++#endif
++
++#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
++ ___DEFINE_XEN_GUEST_HANDLE(name, type); \
++ ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
++#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
++#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name
++#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
++#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)
++#ifdef __XEN_TOOLS__
++#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
++#endif
++
++#if defined(__i386__)
++#include "xen-x86_32.h"
++#elif defined(__x86_64__)
++#include "xen-x86_64.h"
++#endif
++
++#ifndef __ASSEMBLY__
++typedef unsigned long xen_pfn_t;
++#define PRI_xen_pfn "lx"
++#endif
++
++/*
++ * SEGMENT DESCRIPTOR TABLES
++ */
++/*
++ * A number of GDT entries are reserved by Xen. These are not situated at the
++ * start of the GDT because some stupid OSes export hard-coded selector values
++ * in their ABI. These hard-coded values are always near the start of the GDT,
++ * so Xen places itself out of the way, at the far end of the GDT.
++ */
++#define FIRST_RESERVED_GDT_PAGE 14
++#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
++#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
++
++/* Maximum number of virtual CPUs in multi-processor guests. */
++#define MAX_VIRT_CPUS 32
++
++
++/* Machine check support */
++#include "xen-mca.h"
++
++#ifndef __ASSEMBLY__
++
++typedef unsigned long xen_ulong_t;
++
++/*
++ * Send an array of these to HYPERVISOR_set_trap_table().
++ * The privilege level specifies which modes may enter a trap via a software
++ * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
++ * privilege levels as follows:
++ * Level == 0: Noone may enter
++ * Level == 1: Kernel may enter
++ * Level == 2: Kernel may enter
++ * Level == 3: Everyone may enter
++ */
++#define TI_GET_DPL(_ti) ((_ti)->flags & 3)
++#define TI_GET_IF(_ti) ((_ti)->flags & 4)
++#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl))
++#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2))
++struct trap_info {
++ uint8_t vector; /* exception vector */
++ uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
++ uint16_t cs; /* code selector */
++ unsigned long address; /* code offset */
++};
++typedef struct trap_info trap_info_t;
++DEFINE_XEN_GUEST_HANDLE(trap_info_t);
++
++typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
++
++/*
++ * The following is all CPU context. Note that the fpu_ctxt block is filled
++ * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
++ */
++struct vcpu_guest_context {
++ /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
++ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
++#define VGCF_I387_VALID (1<<0)
++#define VGCF_IN_KERNEL (1<<2)
++#define _VGCF_i387_valid 0
++#define VGCF_i387_valid (1<<_VGCF_i387_valid)
++#define _VGCF_in_kernel 2
++#define VGCF_in_kernel (1<<_VGCF_in_kernel)
++#define _VGCF_failsafe_disables_events 3
++#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
++#define _VGCF_syscall_disables_events 4
++#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events)
++#define _VGCF_online 5
++#define VGCF_online (1<<_VGCF_online)
++ unsigned long flags; /* VGCF_* flags */
++ struct cpu_user_regs user_regs; /* User-level CPU registers */
++ struct trap_info trap_ctxt[256]; /* Virtual IDT */
++ unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
++ unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
++ unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
++ /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
++ unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
++ unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
++#ifdef __i386__
++ unsigned long event_callback_cs; /* CS:EIP of event callback */
++ unsigned long event_callback_eip;
++ unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
++ unsigned long failsafe_callback_eip;
++#else
++ unsigned long event_callback_eip;
++ unsigned long failsafe_callback_eip;
++#ifdef __XEN__
++ union {
++ unsigned long syscall_callback_eip;
++ struct {
++ unsigned int event_callback_cs; /* compat CS of event cb */
++ unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */
++ };
++ };
++#else
++ unsigned long syscall_callback_eip;
++#endif
++#endif
++ unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
++#ifdef __x86_64__
++ /* Segment base addresses. */
++ uint64_t fs_base;
++ uint64_t gs_base_kernel;
++ uint64_t gs_base_user;
++#endif
++};
++typedef struct vcpu_guest_context vcpu_guest_context_t;
++DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
++
++struct arch_shared_info {
++ unsigned long max_pfn; /* max pfn that appears in table */
++ /* Frame containing list of mfns containing list of mfns containing p2m. */
++ xen_pfn_t pfn_to_mfn_frame_list_list;
++ unsigned long nmi_reason;
++ uint64_t pad[32];
++};
++typedef struct arch_shared_info arch_shared_info_t;
++
++#endif /* !__ASSEMBLY__ */
++
++/*
++ * Prefix forces emulation of some non-trapping instructions.
++ * Currently only CPUID.
++ */
++#ifdef __ASSEMBLY__
++#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
++#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
++#else
++#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
++#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
++#endif
++
++#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-mca.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/xen-mca.h
+--- linux-2.6.18.8/include/xen/interface/arch-x86/xen-mca.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/xen-mca.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,279 @@
++/******************************************************************************
++ * arch-x86/mca.h
++ *
++ * Contributed by Advanced Micro Devices, Inc.
++ * Author: Christoph Egger <Christoph.Egger@amd.com>
++ *
++ * Guest OS machine check interface to x86 Xen.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++/* Full MCA functionality has the following Usecases from the guest side:
++ *
++ * Must have's:
++ * 1. Dom0 and DomU register machine check trap callback handlers
++ * (already done via "set_trap_table" hypercall)
++ * 2. Dom0 registers machine check event callback handler
++ * (doable via EVTCHNOP_bind_virq)
++ * 3. Dom0 and DomU fetches machine check data
++ * 4. Dom0 wants Xen to notify a DomU
++ * 5. Dom0 gets DomU ID from physical address
++ * 6. Dom0 wants Xen to kill DomU (already done for "xm destroy")
++ *
++ * Nice to have's:
++ * 7. Dom0 wants Xen to deactivate a physical CPU
++ * This is better done as separate task, physical CPU hotplugging,
++ * and hypercall(s) should be sysctl's
++ * 8. Page migration proposed from Xen NUMA work, where Dom0 can tell Xen to
++ * move a DomU (or Dom0 itself) away from a malicious page
++ * producing correctable errors.
++ * 9. offlining physical page:
++ * Xen free's and never re-uses a certain physical page.
++ * 10. Testfacility: Allow Dom0 to write values into machine check MSR's
++ * and tell Xen to trigger a machine check
++ */
++
++#ifndef __XEN_PUBLIC_ARCH_X86_MCA_H__
++#define __XEN_PUBLIC_ARCH_X86_MCA_H__
++
++/* Hypercall */
++#define __HYPERVISOR_mca __HYPERVISOR_arch_0
++
++#define XEN_MCA_INTERFACE_VERSION 0x03000001
++
++/* IN: Dom0 calls hypercall from MC event handler. */
++#define XEN_MC_CORRECTABLE 0x0
++/* IN: Dom0/DomU calls hypercall from MC trap handler. */
++#define XEN_MC_TRAP 0x1
++/* XEN_MC_CORRECTABLE and XEN_MC_TRAP are mutually exclusive. */
++
++/* OUT: All is ok */
++#define XEN_MC_OK 0x0
++/* OUT: Domain could not fetch data. */
++#define XEN_MC_FETCHFAILED 0x1
++/* OUT: There was no machine check data to fetch. */
++#define XEN_MC_NODATA 0x2
++/* OUT: Between notification time and this hypercall an other
++ * (most likely) correctable error happened. The fetched data,
++ * does not match the original machine check data. */
++#define XEN_MC_NOMATCH 0x4
++
++/* OUT: DomU did not register MC NMI handler. Try something else. */
++#define XEN_MC_CANNOTHANDLE 0x8
++/* OUT: Notifying DomU failed. Retry later or try something else. */
++#define XEN_MC_NOTDELIVERED 0x10
++/* Note, XEN_MC_CANNOTHANDLE and XEN_MC_NOTDELIVERED are mutually exclusive. */
++
++
++#ifndef __ASSEMBLY__
++
++#define VIRQ_MCA VIRQ_ARCH_0 /* G. (DOM0) Machine Check Architecture */
++
++/*
++ * Machine Check Architecure:
++ * structs are read-only and used to report all kinds of
++ * correctable and uncorrectable errors detected by the HW.
++ * Dom0 and DomU: register a handler to get notified.
++ * Dom0 only: Correctable errors are reported via VIRQ_MCA
++ * Dom0 and DomU: Uncorrectable errors are reported via nmi handlers
++ */
++#define MC_TYPE_GLOBAL 0
++#define MC_TYPE_BANK 1
++#define MC_TYPE_EXTENDED 2
++
++struct mcinfo_common {
++ uint16_t type; /* structure type */
++ uint16_t size; /* size of this struct in bytes */
++};
++
++
++#define MC_FLAG_CORRECTABLE (1 << 0)
++#define MC_FLAG_UNCORRECTABLE (1 << 1)
++
++/* contains global x86 mc information */
++struct mcinfo_global {
++ struct mcinfo_common common;
++
++ /* running domain at the time in error (most likely the impacted one) */
++ uint16_t mc_domid;
++ uint32_t mc_socketid; /* physical socket of the physical core */
++ uint16_t mc_coreid; /* physical impacted core */
++ uint16_t mc_core_threadid; /* core thread of physical core */
++ uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */
++ uint64_t mc_gstatus; /* global status */
++ uint32_t mc_flags;
++};
++
++/* contains bank local x86 mc information */
++struct mcinfo_bank {
++ struct mcinfo_common common;
++
++ uint16_t mc_bank; /* bank nr */
++ uint16_t mc_domid; /* Usecase 5: domain referenced by mc_addr on dom0
++ * and if mc_addr is valid. Never valid on DomU. */
++ uint64_t mc_status; /* bank status */
++ uint64_t mc_addr; /* bank address, only valid
++ * if addr bit is set in mc_status */
++ uint64_t mc_misc;
++};
++
++
++struct mcinfo_msr {
++ uint64_t reg; /* MSR */
++ uint64_t value; /* MSR value */
++};
++
++/* contains mc information from other
++ * or additional mc MSRs */
++struct mcinfo_extended {
++ struct mcinfo_common common;
++
++ /* You can fill up to five registers.
++ * If you need more, then use this structure
++ * multiple times. */
++
++ uint32_t mc_msrs; /* Number of msr with valid values. */
++ struct mcinfo_msr mc_msr[5];
++};
++
++#define MCINFO_HYPERCALLSIZE 1024
++#define MCINFO_MAXSIZE 768
++
++struct mc_info {
++ /* Number of mcinfo_* entries in mi_data */
++ uint32_t mi_nentries;
++
++ uint8_t mi_data[MCINFO_MAXSIZE - sizeof(uint32_t)];
++};
++typedef struct mc_info mc_info_t;
++
++
++
++/*
++ * OS's should use these instead of writing their own lookup function
++ * each with its own bugs and drawbacks.
++ * We use macros instead of static inline functions to allow guests
++ * to include this header in assembly files (*.S).
++ */
++/* Prototype:
++ * uint32_t x86_mcinfo_nentries(struct mc_info *mi);
++ */
++#define x86_mcinfo_nentries(_mi) \
++ (_mi)->mi_nentries
++/* Prototype:
++ * struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi);
++ */
++#define x86_mcinfo_first(_mi) \
++ (struct mcinfo_common *)((_mi)->mi_data)
++/* Prototype:
++ * struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic);
++ */
++#define x86_mcinfo_next(_mic) \
++ (struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size)
++
++/* Prototype:
++ * void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type);
++ */
++#define x86_mcinfo_lookup(_ret, _mi, _type) \
++ do { \
++ uint32_t found, i; \
++ struct mcinfo_common *_mic; \
++ \
++ found = 0; \
++ (_ret) = NULL; \
++ if (_mi == NULL) break; \
++ _mic = x86_mcinfo_first(_mi); \
++ for (i = 0; i < x86_mcinfo_nentries(_mi); i++) { \
++ if (_mic->type == (_type)) { \
++ found = 1; \
++ break; \
++ } \
++ _mic = x86_mcinfo_next(_mic); \
++ } \
++ (_ret) = found ? _mic : NULL; \
++ } while (0)
++
++
++/* Usecase 1
++ * Register machine check trap callback handler
++ * (already done via "set_trap_table" hypercall)
++ */
++
++/* Usecase 2
++ * Dom0 registers machine check event callback handler
++ * done by EVTCHNOP_bind_virq
++ */
++
++/* Usecase 3
++ * Fetch machine check data from hypervisor.
++ * Note, this hypercall is special, because both Dom0 and DomU must use this.
++ */
++#define XEN_MC_fetch 1
++struct xen_mc_fetch {
++ /* IN/OUT variables. */
++ uint32_t flags;
++
++/* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */
++/* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED, XEN_MC_NODATA, XEN_MC_NOMATCH */
++
++ /* OUT variables. */
++ uint32_t fetch_idx; /* only useful for Dom0 for the notify hypercall */
++ struct mc_info mc_info;
++};
++typedef struct xen_mc_fetch xen_mc_fetch_t;
++DEFINE_XEN_GUEST_HANDLE(xen_mc_fetch_t);
++
++
++/* Usecase 4
++ * This tells the hypervisor to notify a DomU about the machine check error
++ */
++#define XEN_MC_notifydomain 2
++struct xen_mc_notifydomain {
++ /* IN variables. */
++ uint16_t mc_domid; /* The unprivileged domain to notify. */
++ uint16_t mc_vcpuid; /* The vcpu in mc_domid to notify.
++ * Usually echo'd value from the fetch hypercall. */
++ uint32_t fetch_idx; /* echo'd value from the fetch hypercall. */
++
++ /* IN/OUT variables. */
++ uint32_t flags;
++
++/* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */
++/* OUT: XEN_MC_OK, XEN_MC_CANNOTHANDLE, XEN_MC_NOTDELIVERED, XEN_MC_NOMATCH */
++};
++typedef struct xen_mc_notifydomain xen_mc_notifydomain_t;
++DEFINE_XEN_GUEST_HANDLE(xen_mc_notifydomain_t);
++
++
++struct xen_mc {
++ uint32_t cmd;
++ uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */
++ union {
++ struct xen_mc_fetch mc_fetch;
++ struct xen_mc_notifydomain mc_notifydomain;
++ uint8_t pad[MCINFO_HYPERCALLSIZE];
++ } u;
++};
++typedef struct xen_mc xen_mc_t;
++DEFINE_XEN_GUEST_HANDLE(xen_mc_t);
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_32.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/xen-x86_32.h
+--- linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_32.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/xen-x86_32.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,180 @@
+/******************************************************************************
+ * xen-x86_32.h
+ *
@@ -128416,6 +198225,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_32.h linux-2.6.
+#define MACH2PHYS_VIRT_END_PAE \
+ mk_unsigned_long(__MACH2PHYS_VIRT_END_PAE)
+
++/* Non-PAE bounds are obsolete. */
+#define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000
+#define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000
+#define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000
@@ -128426,15 +198236,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_32.h linux-2.6.
+#define MACH2PHYS_VIRT_END_NONPAE \
+ mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE)
+
-+#ifdef CONFIG_X86_PAE
+#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE
+#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE
+#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE
-+#else
-+#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_NONPAE
-+#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_NONPAE
-+#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_NONPAE
-+#endif
+
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
@@ -128525,10 +198329,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_32.h linux-2.6.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_64.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/xen-x86_64.h
---- linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_64.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/xen-x86_64.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,211 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_64.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/xen-x86_64.h
+--- linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_64.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86/xen-x86_64.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,212 @@
+/******************************************************************************
+ * xen-x86_64.h
+ *
@@ -128628,8 +198432,6 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_64.h linux-2.6.
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#endif
+
-+#ifndef __ASSEMBLY__
-+
+/*
+ * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
+ * @which == SEGBASE_* ; @base == 64-bit base address
@@ -128664,13 +198466,16 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_64.h linux-2.6.
+#define _VGCF_in_syscall 8
+#define VGCF_in_syscall (1<<_VGCF_in_syscall)
+#define VGCF_IN_SYSCALL VGCF_in_syscall
++
++#ifndef __ASSEMBLY__
++
+struct iret_context {
+ /* Top of stack (%rsp at point of hypercall). */
+ uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
+ /* Bottom of iret stack frame. */
+};
+
-+#ifdef __GNUC__
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
+#define __DECL_REG(name) union { \
+ uint64_t r ## name, e ## name; \
@@ -128740,211 +198545,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen-x86_64.h linux-2.6.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86/xen.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/xen.h
---- linux-2.6.18.8/include/xen/interface/arch-x86/xen.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86/xen.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,198 @@
-+/******************************************************************************
-+ * arch-x86/xen.h
-+ *
-+ * Guest OS interface to x86 Xen.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to
-+ * deal in the Software without restriction, including without limitation the
-+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-+ * sell copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ * DEALINGS IN THE SOFTWARE.
-+ *
-+ * Copyright (c) 2004-2006, K A Fraser
-+ */
-+
-+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
-+#define __XEN_PUBLIC_ARCH_X86_XEN_H__
-+
-+/* Structural guest handles introduced in 0x00030201. */
-+#if __XEN_INTERFACE_VERSION__ >= 0x00030201
-+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
-+ typedef struct { type *p; } __guest_handle_ ## name
-+#else
-+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
-+ typedef type * __guest_handle_ ## name
-+#endif
-+
-+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
-+ ___DEFINE_XEN_GUEST_HANDLE(name, type); \
-+ ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
-+#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
-+#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name
-+#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
-+#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)
-+#ifdef __XEN_TOOLS__
-+#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
-+#endif
-+
-+#if defined(__i386__)
-+#include "xen-x86_32.h"
-+#elif defined(__x86_64__)
-+#include "xen-x86_64.h"
-+#endif
-+
-+#ifndef __ASSEMBLY__
-+typedef unsigned long xen_pfn_t;
-+#define PRI_xen_pfn "lx"
-+#endif
-+
-+/*
-+ * SEGMENT DESCRIPTOR TABLES
-+ */
-+/*
-+ * A number of GDT entries are reserved by Xen. These are not situated at the
-+ * start of the GDT because some stupid OSes export hard-coded selector values
-+ * in their ABI. These hard-coded values are always near the start of the GDT,
-+ * so Xen places itself out of the way, at the far end of the GDT.
-+ */
-+#define FIRST_RESERVED_GDT_PAGE 14
-+#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
-+#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
-+
-+/* Maximum number of virtual CPUs in multi-processor guests. */
-+#define MAX_VIRT_CPUS 32
-+
-+#ifndef __ASSEMBLY__
-+
-+typedef unsigned long xen_ulong_t;
-+
-+/*
-+ * Send an array of these to HYPERVISOR_set_trap_table().
-+ * The privilege level specifies which modes may enter a trap via a software
-+ * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
-+ * privilege levels as follows:
-+ * Level == 0: Noone may enter
-+ * Level == 1: Kernel may enter
-+ * Level == 2: Kernel may enter
-+ * Level == 3: Everyone may enter
-+ */
-+#define TI_GET_DPL(_ti) ((_ti)->flags & 3)
-+#define TI_GET_IF(_ti) ((_ti)->flags & 4)
-+#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl))
-+#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2))
-+struct trap_info {
-+ uint8_t vector; /* exception vector */
-+ uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
-+ uint16_t cs; /* code selector */
-+ unsigned long address; /* code offset */
-+};
-+typedef struct trap_info trap_info_t;
-+DEFINE_XEN_GUEST_HANDLE(trap_info_t);
-+
-+typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
-+
-+/*
-+ * The following is all CPU context. Note that the fpu_ctxt block is filled
-+ * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
-+ */
-+struct vcpu_guest_context {
-+ /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
-+ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
-+#define VGCF_I387_VALID (1<<0)
-+#define VGCF_IN_KERNEL (1<<2)
-+#define _VGCF_i387_valid 0
-+#define VGCF_i387_valid (1<<_VGCF_i387_valid)
-+#define _VGCF_in_kernel 2
-+#define VGCF_in_kernel (1<<_VGCF_in_kernel)
-+#define _VGCF_failsafe_disables_events 3
-+#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
-+#define _VGCF_syscall_disables_events 4
-+#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events)
-+#define _VGCF_online 5
-+#define VGCF_online (1<<_VGCF_online)
-+ unsigned long flags; /* VGCF_* flags */
-+ struct cpu_user_regs user_regs; /* User-level CPU registers */
-+ struct trap_info trap_ctxt[256]; /* Virtual IDT */
-+ unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
-+ unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
-+ unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
-+ /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
-+ unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
-+ unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
-+#ifdef __i386__
-+ unsigned long event_callback_cs; /* CS:EIP of event callback */
-+ unsigned long event_callback_eip;
-+ unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
-+ unsigned long failsafe_callback_eip;
-+#else
-+ unsigned long event_callback_eip;
-+ unsigned long failsafe_callback_eip;
-+#ifdef __XEN__
-+ union {
-+ unsigned long syscall_callback_eip;
-+ struct {
-+ unsigned int event_callback_cs; /* compat CS of event cb */
-+ unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */
-+ };
-+ };
-+#else
-+ unsigned long syscall_callback_eip;
-+#endif
-+#endif
-+ unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
-+#ifdef __x86_64__
-+ /* Segment base addresses. */
-+ uint64_t fs_base;
-+ uint64_t gs_base_kernel;
-+ uint64_t gs_base_user;
-+#endif
-+};
-+typedef struct vcpu_guest_context vcpu_guest_context_t;
-+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
-+
-+struct arch_shared_info {
-+ unsigned long max_pfn; /* max pfn that appears in table */
-+ /* Frame containing list of mfns containing list of mfns containing p2m. */
-+ xen_pfn_t pfn_to_mfn_frame_list_list;
-+ unsigned long nmi_reason;
-+ uint64_t pad[32];
-+};
-+typedef struct arch_shared_info arch_shared_info_t;
-+
-+#endif /* !__ASSEMBLY__ */
-+
-+/*
-+ * Prefix forces emulation of some non-trapping instructions.
-+ * Currently only CPUID.
-+ */
-+#ifdef __ASSEMBLY__
-+#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
-+#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
-+#else
-+#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
-+#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
-+#endif
-+
-+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
-+
-+/*
-+ * Local variables:
-+ * mode: C
-+ * c-set-style: "BSD"
-+ * c-basic-offset: 4
-+ * tab-width: 4
-+ * indent-tabs-mode: nil
-+ * End:
-+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86_32.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86_32.h
---- linux-2.6.18.8/include/xen/interface/arch-x86_32.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86_32.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86_32.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86_32.h
+--- linux-2.6.18.8/include/xen/interface/arch-x86_32.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86_32.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * arch-x86_32.h
@@ -128973,9 +198576,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86_32.h linux-2.6.18-xen-3
+ */
+
+#include "arch-x86/xen.h"
-diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86_64.h linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86_64.h
---- linux-2.6.18.8/include/xen/interface/arch-x86_64.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/arch-x86_64.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86_64.h linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86_64.h
+--- linux-2.6.18.8/include/xen/interface/arch-x86_64.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/arch-x86_64.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * arch-x86_64.h
@@ -129004,9 +198607,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/arch-x86_64.h linux-2.6.18-xen-3
+ */
+
+#include "arch-x86/xen.h"
-diff -rpuN linux-2.6.18.8/include/xen/interface/callback.h linux-2.6.18-xen-3.2.0/include/xen/interface/callback.h
---- linux-2.6.18.8/include/xen/interface/callback.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/callback.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/callback.h linux-2.6.18-xen-3.3.0/include/xen/interface/callback.h
+--- linux-2.6.18.8/include/xen/interface/callback.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/callback.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,121 @@
+/******************************************************************************
+ * callback.h
@@ -129129,9 +198732,51 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/callback.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/dom0_ops.h linux-2.6.18-xen-3.2.0/include/xen/interface/dom0_ops.h
---- linux-2.6.18.8/include/xen/interface/dom0_ops.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/dom0_ops.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/COPYING linux-2.6.18-xen-3.3.0/include/xen/interface/COPYING
+--- linux-2.6.18.8/include/xen/interface/COPYING 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/COPYING 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,38 @@
++XEN NOTICE
++==========
++
++This copyright applies to all files within this subdirectory and its
++subdirectories:
++ include/public/*.h
++ include/public/hvm/*.h
++ include/public/io/*.h
++
++The intention is that these files can be freely copied into the source
++tree of an operating system when porting that OS to run on Xen. Doing
++so does *not* cause the OS to become subject to the terms of the GPL.
++
++All other files in the Xen source distribution are covered by version
++2 of the GNU General Public License except where explicitly stated
++otherwise within individual source files.
++
++ -- Keir Fraser (on behalf of the Xen team)
++
++=====================================================================
++
++Permission is hereby granted, free of charge, to any person obtaining a copy
++of this software and associated documentation files (the "Software"), to
++deal in the Software without restriction, including without limitation the
++rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++sell copies of the Software, and to permit persons to whom the Software is
++furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice shall be included in
++all copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++DEALINGS IN THE SOFTWARE.
+diff -rpuN linux-2.6.18.8/include/xen/interface/dom0_ops.h linux-2.6.18-xen-3.3.0/include/xen/interface/dom0_ops.h
+--- linux-2.6.18.8/include/xen/interface/dom0_ops.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/dom0_ops.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,120 @@
+/******************************************************************************
+ * dom0_ops.h
@@ -129253,10 +198898,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/dom0_ops.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/include/xen/interface/domctl.h
---- linux-2.6.18.8/include/xen/interface/domctl.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/domctl.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,609 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.3.0/include/xen/interface/domctl.h
+--- linux-2.6.18.8/include/xen/interface/domctl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/domctl.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,676 @@
+/******************************************************************************
+ * domctl.h
+ *
@@ -129312,6 +198957,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/
+ /* Is this an HVM guest (as opposed to a PV guest)? */
+#define _XEN_DOMCTL_CDF_hvm_guest 0
+#define XEN_DOMCTL_CDF_hvm_guest (1U<<_XEN_DOMCTL_CDF_hvm_guest)
++ /* Use hardware-assisted paging if available? */
++#define _XEN_DOMCTL_CDF_hap 1
++#define XEN_DOMCTL_CDF_hap (1U<<_XEN_DOMCTL_CDF_hap)
+ uint32_t flags;
+};
+typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
@@ -129632,6 +199280,8 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/
+#define XEN_DOMAINSETUP_hvm_guest (1UL<<_XEN_DOMAINSETUP_hvm_guest)
+#define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save) */
+#define XEN_DOMAINSETUP_query (1UL<<_XEN_DOMAINSETUP_query)
++#define _XEN_DOMAINSETUP_sioemu_guest 2
++#define XEN_DOMAINSETUP_sioemu_guest (1UL<<_XEN_DOMAINSETUP_sioemu_guest)
+typedef struct xen_domctl_arch_setup {
+ uint64_aligned_t flags; /* XEN_DOMAINSETUP_* */
+#ifdef __ia64__
@@ -129695,18 +199345,31 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/
+/* Assign PCI device to HVM guest. Sets up IOMMU structures. */
+#define XEN_DOMCTL_assign_device 37
+#define XEN_DOMCTL_test_assign_device 45
++#define XEN_DOMCTL_deassign_device 47
+struct xen_domctl_assign_device {
+ uint32_t machine_bdf; /* machine PCI ID of assigned device */
+};
+typedef struct xen_domctl_assign_device xen_domctl_assign_device_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t);
+
++/* Retrieve sibling devices infomation of machine_bdf */
++#define XEN_DOMCTL_get_device_group 50
++struct xen_domctl_get_device_group {
++ uint32_t machine_bdf; /* IN */
++ uint32_t max_sdevs; /* IN */
++ uint32_t num_sdevs; /* OUT */
++ XEN_GUEST_HANDLE_64(uint32) sdev_array; /* OUT */
++};
++typedef struct xen_domctl_get_device_group xen_domctl_get_device_group_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_get_device_group_t);
+
+/* Pass-through interrupts: bind real irq -> hvm devfn. */
+#define XEN_DOMCTL_bind_pt_irq 38
++#define XEN_DOMCTL_unbind_pt_irq 48
+typedef enum pt_irq_type_e {
+ PT_IRQ_TYPE_PCI,
-+ PT_IRQ_TYPE_ISA
++ PT_IRQ_TYPE_ISA,
++ PT_IRQ_TYPE_MSI,
+} pt_irq_type_t;
+struct xen_domctl_bind_pt_irq {
+ uint32_t machine_irq;
@@ -129722,6 +199385,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/
+ uint8_t device;
+ uint8_t intx;
+ } pci;
++ struct {
++ uint8_t gvec;
++ uint32_t gflags;
++ } msi;
+ } u;
+};
+typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t;
@@ -129813,6 +199480,45 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/
+typedef struct xen_domctl_set_opt_feature xen_domctl_set_opt_feature_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_opt_feature_t);
+
++/*
++ * Set the target domain for a domain
++ */
++#define XEN_DOMCTL_set_target 46
++struct xen_domctl_set_target {
++ domid_t target;
++};
++typedef struct xen_domctl_set_target xen_domctl_set_target_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_target_t);
++
++#if defined(__i386__) || defined(__x86_64__)
++# define XEN_CPUID_INPUT_UNUSED 0xFFFFFFFF
++# define XEN_DOMCTL_set_cpuid 49
++struct xen_domctl_cpuid {
++ unsigned int input[2];
++ unsigned int eax;
++ unsigned int ebx;
++ unsigned int ecx;
++ unsigned int edx;
++};
++typedef struct xen_domctl_cpuid xen_domctl_cpuid_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpuid_t);
++#endif
++
++#define XEN_DOMCTL_subscribe 29
++struct xen_domctl_subscribe {
++ uint32_t port; /* IN */
++};
++typedef struct xen_domctl_subscribe xen_domctl_subscribe_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_subscribe_t);
++
++/*
++ * Define the maximum machine address size which should be allocated
++ * to a guest.
++ */
++#define XEN_DOMCTL_set_machine_address_size 51
++#define XEN_DOMCTL_get_machine_address_size 52
++
++
+struct xen_domctl {
+ uint32_t cmd;
+ uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
@@ -129842,6 +199548,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/
+ struct xen_domctl_hvmcontext hvmcontext;
+ struct xen_domctl_address_size address_size;
+ struct xen_domctl_sendtrigger sendtrigger;
++ struct xen_domctl_get_device_group get_device_group;
+ struct xen_domctl_assign_device assign_device;
+ struct xen_domctl_bind_pt_irq bind_pt_irq;
+ struct xen_domctl_memory_mapping memory_mapping;
@@ -129849,6 +199556,11 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/
+ struct xen_domctl_pin_mem_cacheattr pin_mem_cacheattr;
+ struct xen_domctl_ext_vcpucontext ext_vcpucontext;
+ struct xen_domctl_set_opt_feature set_opt_feature;
++ struct xen_domctl_set_target set_target;
++ struct xen_domctl_subscribe subscribe;
++#if defined(__i386__) || defined(__x86_64__)
++ struct xen_domctl_cpuid cpuid;
++#endif
+ uint8_t pad[128];
+ } u;
+};
@@ -129866,9 +199578,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/domctl.h linux-2.6.18-xen-3.2.0/
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/elfnote.h linux-2.6.18-xen-3.2.0/include/xen/interface/elfnote.h
---- linux-2.6.18.8/include/xen/interface/elfnote.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/elfnote.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/elfnote.h linux-2.6.18-xen-3.3.0/include/xen/interface/elfnote.h
+--- linux-2.6.18.8/include/xen/interface/elfnote.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/elfnote.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,233 @@
+/******************************************************************************
+ * elfnote.h
@@ -130103,9 +199815,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/elfnote.h linux-2.6.18-xen-3.2.0
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/elfstructs.h linux-2.6.18-xen-3.2.0/include/xen/interface/elfstructs.h
---- linux-2.6.18.8/include/xen/interface/elfstructs.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/elfstructs.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/elfstructs.h linux-2.6.18-xen-3.3.0/include/xen/interface/elfstructs.h
+--- linux-2.6.18.8/include/xen/interface/elfstructs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/elfstructs.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,527 @@
+#ifndef __XEN_PUBLIC_ELFSTRUCTS_H__
+#define __XEN_PUBLIC_ELFSTRUCTS_H__ 1
@@ -130634,9 +200346,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/elfstructs.h linux-2.6.18-xen-3.
+#endif
+
+#endif /* __XEN_PUBLIC_ELFSTRUCTS_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/event_channel.h linux-2.6.18-xen-3.2.0/include/xen/interface/event_channel.h
---- linux-2.6.18.8/include/xen/interface/event_channel.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/event_channel.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/event_channel.h linux-2.6.18-xen-3.3.0/include/xen/interface/event_channel.h
+--- linux-2.6.18.8/include/xen/interface/event_channel.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/event_channel.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,264 @@
+/******************************************************************************
+ * event_channel.h
@@ -130902,9 +200614,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/event_channel.h linux-2.6.18-xen
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/features.h linux-2.6.18-xen-3.2.0/include/xen/interface/features.h
---- linux-2.6.18.8/include/xen/interface/features.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/features.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/features.h linux-2.6.18-xen-3.3.0/include/xen/interface/features.h
+--- linux-2.6.18.8/include/xen/interface/features.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/features.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,74 @@
+/******************************************************************************
+ * features.h
@@ -130980,9 +200692,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/features.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/Makefile linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/Makefile
---- linux-2.6.18.8/include/xen/interface/foreign/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/Makefile 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/Makefile linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/Makefile
+--- linux-2.6.18.8/include/xen/interface/foreign/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,37 @@
+XEN_ROOT=../../../..
+include $(XEN_ROOT)/Config.mk
@@ -131021,9 +200733,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/Makefile linux-2.6.18-xe
+
+checker.c: $(scripts)
+ python mkchecker.py $(XEN_TARGET_ARCH) $@ $(architectures)
-diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/mkchecker.py linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/mkchecker.py
---- linux-2.6.18.8/include/xen/interface/foreign/mkchecker.py 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/mkchecker.py 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/mkchecker.py linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/mkchecker.py
+--- linux-2.6.18.8/include/xen/interface/foreign/mkchecker.py 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/mkchecker.py 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+
@@ -131083,9 +200795,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/mkchecker.py linux-2.6.1
+
+f.close();
+
-diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/mkheader.py linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/mkheader.py
---- linux-2.6.18.8/include/xen/interface/foreign/mkheader.py 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/mkheader.py 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/mkheader.py linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/mkheader.py
+--- linux-2.6.18.8/include/xen/interface/foreign/mkheader.py 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/mkheader.py 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,167 @@
+#!/usr/bin/python
+
@@ -131254,9 +200966,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/mkheader.py linux-2.6.18
+f.write(output);
+f.close;
+
-diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/reference.size linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/reference.size
---- linux-2.6.18.8/include/xen/interface/foreign/reference.size 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/reference.size 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/reference.size linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/reference.size
+--- linux-2.6.18.8/include/xen/interface/foreign/reference.size 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/reference.size 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,18 @@
+
+structs | x86_32 x86_64 ia64
@@ -131276,9 +200988,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/reference.size linux-2.6
+arch_shared_info | 268 280 272
+shared_info | 2584 3368 4384
+
-diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/structs.py linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/structs.py
---- linux-2.6.18.8/include/xen/interface/foreign/structs.py 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/foreign/structs.py 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/structs.py linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/structs.py
+--- linux-2.6.18.8/include/xen/interface/foreign/structs.py 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/foreign/structs.py 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,58 @@
+# configuration: what needs translation
+
@@ -131338,9 +201050,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/foreign/structs.py linux-2.6.18-
+ "MAX_VIRT_CPUS",
+ "MAX_GUEST_CMDLINE" ];
+
-diff -rpuN linux-2.6.18.8/include/xen/interface/grant_table.h linux-2.6.18-xen-3.2.0/include/xen/interface/grant_table.h
---- linux-2.6.18.8/include/xen/interface/grant_table.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/grant_table.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/grant_table.h linux-2.6.18-xen-3.3.0/include/xen/interface/grant_table.h
+--- linux-2.6.18.8/include/xen/interface/grant_table.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/grant_table.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,431 @@
+/******************************************************************************
+ * grant_table.h
@@ -131773,9 +201485,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/grant_table.h linux-2.6.18-xen-3
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/e820.h linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/e820.h
---- linux-2.6.18.8/include/xen/interface/hvm/e820.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/e820.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/e820.h linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/e820.h
+--- linux-2.6.18.8/include/xen/interface/hvm/e820.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/e820.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,34 @@
+
+/*
@@ -131811,9 +201523,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/e820.h linux-2.6.18-xen-3.2.
+#define HVM_BELOW_4G_MMIO_LENGTH ((1ULL << 32) - HVM_BELOW_4G_MMIO_START)
+
+#endif /* __XEN_PUBLIC_HVM_E820_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/hvm_info_table.h linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/hvm_info_table.h
---- linux-2.6.18.8/include/xen/interface/hvm/hvm_info_table.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/hvm_info_table.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/hvm_info_table.h linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/hvm_info_table.h
+--- linux-2.6.18.8/include/xen/interface/hvm/hvm_info_table.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/hvm_info_table.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,41 @@
+/******************************************************************************
+ * hvm/hvm_info_table.h
@@ -131856,10 +201568,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/hvm_info_table.h linux-2.6.1
+};
+
+#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/hvm_op.h linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/hvm_op.h
---- linux-2.6.18.8/include/xen/interface/hvm/hvm_op.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/hvm_op.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,76 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/hvm_op.h linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/hvm_op.h
+--- linux-2.6.18.8/include/xen/interface/hvm/hvm_op.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/hvm_op.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,131 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
@@ -131935,11 +201647,66 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/hvm_op.h linux-2.6.18-xen-3.
+/* Flushes all VCPU TLBs: @arg must be NULL. */
+#define HVMOP_flush_tlbs 5
+
++/* Following tools-only interfaces may change in future. */
++#if defined(__XEN__) || defined(__XEN_TOOLS__)
++
++/* Track dirty VRAM. */
++#define HVMOP_track_dirty_vram 6
++struct xen_hvm_track_dirty_vram {
++ /* Domain to be tracked. */
++ domid_t domid;
++ /* First pfn to track. */
++ uint64_aligned_t first_pfn;
++ /* Number of pages to track. */
++ uint64_aligned_t nr;
++ /* OUT variable. */
++ /* Dirty bitmap buffer. */
++ XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
++};
++typedef struct xen_hvm_track_dirty_vram xen_hvm_track_dirty_vram_t;
++DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t);
++
++/* Notify that some pages got modified by the Device Model. */
++#define HVMOP_modified_memory 7
++struct xen_hvm_modified_memory {
++ /* Domain to be updated. */
++ domid_t domid;
++ /* First pfn. */
++ uint64_aligned_t first_pfn;
++ /* Number of pages. */
++ uint64_aligned_t nr;
++};
++typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t;
++DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t);
++
++#define HVMOP_set_mem_type 8
++typedef enum {
++ HVMMEM_ram_rw, /* Normal read/write guest RAM */
++ HVMMEM_ram_ro, /* Read-only; writes are discarded */
++ HVMMEM_mmio_dm, /* Reads and write go to the device model */
++} hvmmem_type_t;
++/* Notify that a region of memory is to be treated in a specific way. */
++struct xen_hvm_set_mem_type {
++ /* Domain to be updated. */
++ domid_t domid;
++ /* Memory type */
++ hvmmem_type_t hvmmem_type;
++ /* First pfn. */
++ uint64_aligned_t first_pfn;
++ /* Number of pages. */
++ uint64_aligned_t nr;
++};
++typedef struct xen_hvm_set_mem_type xen_hvm_set_mem_type_t;
++DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_type_t);
++
++
++#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
++
+#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/ioreq.h linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/ioreq.h
---- linux-2.6.18.8/include/xen/interface/hvm/ioreq.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/ioreq.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,133 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/ioreq.h linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/ioreq.h
+--- linux-2.6.18.8/include/xen/interface/hvm/ioreq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/ioreq.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,127 @@
+/*
+ * ioreq.h: I/O request definitions for device models
+ * Copyright (c) 2004, Intel Corporation.
@@ -131976,14 +201743,8 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/ioreq.h linux-2.6.18-xen-3.2
+
+#define IOREQ_TYPE_PIO 0 /* pio */
+#define IOREQ_TYPE_COPY 1 /* mmio ops */
-+#define IOREQ_TYPE_AND 2
-+#define IOREQ_TYPE_OR 3
-+#define IOREQ_TYPE_XOR 4
-+#define IOREQ_TYPE_XCHG 5
-+#define IOREQ_TYPE_ADD 6
+#define IOREQ_TYPE_TIMEOFFSET 7
+#define IOREQ_TYPE_INVALIDATE 8 /* mapcache */
-+#define IOREQ_TYPE_SUB 9
+
+/*
+ * VMExit dispatcher should cooperate with instruction decoder to
@@ -132056,11 +201817,11 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/ioreq.h linux-2.6.18-xen-3.2
+};
+#endif /* defined(__ia64__) */
+
-+#if defined(__i386__) || defined(__x86_64__)
+#define ACPI_PM1A_EVT_BLK_ADDRESS 0x0000000000001f40
+#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04)
+#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08)
-+#endif /* defined(__i386__) || defined(__x86_64__) */
++#define ACPI_GPE0_BLK_ADDRESS (ACPI_PM_TMR_BLK_ADDRESS + 0x20)
++#define ACPI_GPE0_BLK_LEN 0x08
+
+#endif /* _IOREQ_H_ */
+
@@ -132073,10 +201834,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/ioreq.h linux-2.6.18-xen-3.2
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/params.h linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/params.h
---- linux-2.6.18.8/include/xen/interface/hvm/params.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/params.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,86 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/params.h linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/params.h
+--- linux-2.6.18.8/include/xen/interface/hvm/params.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/params.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,98 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
@@ -132160,13 +201921,25 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/params.h linux-2.6.18-xen-3.
+#define HVMPTM_no_missed_ticks_pending 2
+#define HVMPTM_one_missed_tick_pending 3
+
-+#define HVM_NR_PARAMS 11
++/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
++#define HVM_PARAM_HPET_ENABLED 11
++
++/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
++#define HVM_PARAM_IDENT_PT 12
++
++/* Device Model domain, defaults to 0. */
++#define HVM_PARAM_DM_DOMAIN 13
++
++/* ACPI S state: currently support S0 and S3 on x86. */
++#define HVM_PARAM_ACPI_S_STATE 14
++
++#define HVM_NR_PARAMS 15
+
+#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/save.h linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/save.h
---- linux-2.6.18.8/include/xen/interface/hvm/save.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/save.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,84 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/save.h linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/save.h
+--- linux-2.6.18.8/include/xen/interface/hvm/save.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/save.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,88 @@
+/*
+ * hvm/save.h
+ *
@@ -132208,6 +201981,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/save.h linux-2.6.18-xen-3.2.
+ * Internal mechanisms should be kept in Xen-private headers.
+ */
+
++#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
++#error "Anonymous structs/unions are a GNU extension."
++#endif
++
+/*
+ * Each entry is preceded by a descriptor giving its type and length
+ */
@@ -132251,9 +202028,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/save.h linux-2.6.18-xen-3.2.
+#endif
+
+#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/vmx_assist.h linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/vmx_assist.h
---- linux-2.6.18.8/include/xen/interface/hvm/vmx_assist.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/hvm/vmx_assist.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/vmx_assist.h linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/vmx_assist.h
+--- linux-2.6.18.8/include/xen/interface/hvm/vmx_assist.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/hvm/vmx_assist.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,122 @@
+/*
+ * vmx_assist.h: Context definitions for the VMXASSIST world switch.
@@ -132377,9 +202154,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/hvm/vmx_assist.h linux-2.6.18-xe
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/blkif.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/blkif.h
---- linux-2.6.18.8/include/xen/interface/io/blkif.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/blkif.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/blkif.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/blkif.h
+--- linux-2.6.18.8/include/xen/interface/io/blkif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/blkif.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,141 @@
+/******************************************************************************
+ * blkif.h
@@ -132522,9 +202299,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/blkif.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/console.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/console.h
---- linux-2.6.18.8/include/xen/interface/io/console.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/console.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/console.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/console.h
+--- linux-2.6.18.8/include/xen/interface/io/console.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/console.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * console.h
@@ -132577,10 +202354,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/console.h linux-2.6.18-xen-3.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/fbif.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/fbif.h
---- linux-2.6.18.8/include/xen/interface/io/fbif.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/fbif.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,138 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/fbif.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/fbif.h
+--- linux-2.6.18.8/include/xen/interface/io/fbif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/fbif.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,176 @@
+/*
+ * fbif.h -- Xen virtual frame buffer device
+ *
@@ -132633,12 +202410,29 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/fbif.h linux-2.6.18-xen-3.2.0
+ int32_t height; /* rect height */
+};
+
++/*
++ * Framebuffer resize notification event
++ * Capable backend sets feature-resize in xenstore.
++ */
++#define XENFB_TYPE_RESIZE 3
++
++struct xenfb_resize
++{
++ uint8_t type; /* XENFB_TYPE_RESIZE */
++ int32_t width; /* width in pixels */
++ int32_t height; /* height in pixels */
++ int32_t stride; /* stride in bytes */
++ int32_t depth; /* depth in bits */
++ int32_t offset; /* offset of the framebuffer in bytes */
++};
++
+#define XENFB_OUT_EVENT_SIZE 40
+
+union xenfb_out_event
+{
+ uint8_t type;
+ struct xenfb_update update;
++ struct xenfb_resize resize;
+ char pad[XENFB_OUT_EVENT_SIZE];
+};
+
@@ -132646,14 +202440,33 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/fbif.h linux-2.6.18-xen-3.2.0
+
+/*
+ * Frontends should ignore unknown in events.
-+ * No in events currently defined.
+ */
+
++/*
++ * Framebuffer refresh period advice
++ * Backend sends it to advise the frontend their preferred period of
++ * refresh. Frontends that keep the framebuffer constantly up-to-date
++ * just ignore it. Frontends that use the advice should immediately
++ * refresh the framebuffer (and send an update notification event if
++ * those have been requested), then use the update frequency to guide
++ * their periodical refreshs.
++ */
++#define XENFB_TYPE_REFRESH_PERIOD 1
++#define XENFB_NO_REFRESH 0
++
++struct xenfb_refresh_period
++{
++ uint8_t type; /* XENFB_TYPE_UPDATE_PERIOD */
++ uint32_t period; /* period of refresh, in ms,
++ * XENFB_NO_REFRESH if no refresh is needed */
++};
++
+#define XENFB_IN_EVENT_SIZE 40
+
+union xenfb_in_event
+{
+ uint8_t type;
++ struct xenfb_refresh_period refresh_period;
+ char pad[XENFB_IN_EVENT_SIZE];
+};
+
@@ -132692,15 +202505,17 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/fbif.h linux-2.6.18-xen-3.2.0
+ * Each directory page holds PAGE_SIZE / sizeof(*pd)
+ * framebuffer pages, and can thus map up to PAGE_SIZE *
+ * PAGE_SIZE / sizeof(*pd) bytes. With PAGE_SIZE == 4096 and
-+ * sizeof(unsigned long) == 4, that's 4 Megs. Two directory
-+ * pages should be enough for a while.
++ * sizeof(unsigned long) == 4/8, that's 4 Megs 32 bit and 2 Megs
++ * 64 bit. 256 directories give enough room for a 512 Meg
++ * framebuffer with a max resolution of 12,800x10,240. Should
++ * be enough for a while with room leftover for expansion.
+ */
-+ unsigned long pd[2];
++ unsigned long pd[256];
+};
+
+/*
-+ * Wart: xenkbd needs to know resolution. Put it here until a better
-+ * solution is found, but don't leak it to the backend.
++ * Wart: xenkbd needs to know default resolution. Put it here until a
++ * better solution is found, but don't leak it to the backend.
+ */
+#ifdef __KERNEL__
+#define XENFB_WIDTH 800
@@ -132719,10 +202534,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/fbif.h linux-2.6.18-xen-3.2.0
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/fsif.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/fsif.h
---- linux-2.6.18.8/include/xen/interface/io/fsif.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/fsif.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,181 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/fsif.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/fsif.h
+--- linux-2.6.18.8/include/xen/interface/io/fsif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/fsif.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,191 @@
+/******************************************************************************
+ * fsif.h
+ *
@@ -132746,7 +202561,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/fsif.h linux-2.6.18-xen-3.2.0
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
-+ * Copyright (c) 2007, Grzegorz Milos, Sun Microsystems, Inc.
++ * Copyright (c) 2007, Grzegorz Milos, <gm281@cam.ac.uk>.
+ */
+
+#ifndef __XEN_PUBLIC_IO_FSIF_H__
@@ -132779,30 +202594,31 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/fsif.h linux-2.6.18-xen-3.2.0
+
+struct fsif_read_request {
+ uint32_t fd;
-+ grant_ref_t gref;
++ int32_t pad;
+ uint64_t len;
+ uint64_t offset;
++ grant_ref_t grefs[1]; /* Variable length */
+};
+
+struct fsif_write_request {
+ uint32_t fd;
-+ grant_ref_t gref;
++ int32_t pad;
+ uint64_t len;
+ uint64_t offset;
++ grant_ref_t grefs[1]; /* Variable length */
+};
+
+struct fsif_stat_request {
+ uint32_t fd;
-+ grant_ref_t gref;
+};
+
-+/* This structure is a copy of some fields from stat structure, writen to the
-+ * granted page. */
++/* This structure is a copy of some fields from stat structure, returned
++ * via the ring. */
+struct fsif_stat_response {
+ int32_t stat_mode;
+ uint32_t stat_uid;
+ uint32_t stat_gid;
-+ int32_t pad;
++ int32_t stat_ret;
+ int64_t stat_size;
+ int64_t stat_atime;
+ int64_t stat_mtime;
@@ -132890,11 +202706,20 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/fsif.h linux-2.6.18-xen-3.2.0
+ uint16_t id;
+ uint16_t pad1;
+ uint32_t pad2;
-+ uint64_t ret_val;
++ union {
++ uint64_t ret_val;
++ struct fsif_stat_response fstat;
++ };
+};
+
+typedef struct fsif_response fsif_response_t;
+
++#define FSIF_RING_ENTRY_SIZE 64
++
++#define FSIF_NR_READ_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct fsif_read_request)) / \
++ sizeof(grant_ref_t) + 1)
++#define FSIF_NR_WRITE_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct fsif_write_request)) / \
++ sizeof(grant_ref_t) + 1)
+
+DEFINE_RING_TYPES(fsif, struct fsif_request, struct fsif_response);
+
@@ -132904,9 +202729,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/fsif.h linux-2.6.18-xen-3.2.0
+
+
+#endif
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/kbdif.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/kbdif.h
---- linux-2.6.18.8/include/xen/interface/io/kbdif.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/kbdif.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/kbdif.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/kbdif.h
+--- linux-2.6.18.8/include/xen/interface/io/kbdif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/kbdif.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,132 @@
+/*
+ * kbdif.h -- Xen virtual keyboard/mouse
@@ -132975,7 +202800,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/kbdif.h linux-2.6.18-xen-3.2.
+ uint8_t type; /* XENKBD_TYPE_POS */
+ int32_t abs_x; /* absolute X position (in FB pixels) */
+ int32_t abs_y; /* absolute Y position (in FB pixels) */
-+ int32_t abs_z; /* absolute Z position (wheel) */
++ int32_t rel_z; /* relative Z motion (wheel) */
+};
+
+#define XENKBD_IN_EVENT_SIZE 40
@@ -133040,9 +202865,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/kbdif.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/netif.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/netif.h
---- linux-2.6.18.8/include/xen/interface/io/netif.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/netif.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/netif.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/netif.h
+--- linux-2.6.18.8/include/xen/interface/io/netif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/netif.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,205 @@
+/******************************************************************************
+ * netif.h
@@ -133249,10 +203074,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/netif.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/pciif.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/pciif.h
---- linux-2.6.18.8/include/xen/interface/io/pciif.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/pciif.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,83 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/pciif.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/pciif.h
+--- linux-2.6.18.8/include/xen/interface/io/pciif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/pciif.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,101 @@
+/*
+ * PCI Backend/Frontend Common Data Structures & Macros
+ *
@@ -133289,6 +203114,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/pciif.h linux-2.6.18-xen-3.2.
+/* xen_pci_op commands */
+#define XEN_PCI_OP_conf_read (0)
+#define XEN_PCI_OP_conf_write (1)
++#define XEN_PCI_OP_enable_msi (2)
++#define XEN_PCI_OP_disable_msi (3)
++#define XEN_PCI_OP_enable_msix (4)
++#define XEN_PCI_OP_disable_msix (5)
+
+/* xen_pci_op error numbers */
+#define XEN_PCI_ERR_success (0)
@@ -133299,6 +203128,16 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/pciif.h linux-2.6.18-xen-3.2.
+/* XEN_PCI_ERR_op_failed - backend failed to complete the operation */
+#define XEN_PCI_ERR_op_failed (-5)
+
++/*
++ * it should be PAGE_SIZE-sizeof(struct xen_pci_op))/sizeof(struct msix_entry))
++ * Should not exceed 128
++ */
++#define SH_INFO_MAX_VEC 128
++
++struct xen_msix_entry {
++ uint16_t vector;
++ uint16_t entry;
++};
+struct xen_pci_op {
+ /* IN: what action to perform: XEN_PCI_OP_* */
+ uint32_t cmd;
@@ -133317,6 +203156,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/pciif.h linux-2.6.18-xen-3.2.
+
+ /* IN/OUT: Contains the result after a READ or the value to WRITE */
+ uint32_t value;
++ /* IN: Contains extra infor for this operation */
++ uint32_t info;
++ /*IN: param for msi-x */
++ struct xen_msix_entry msix_entries[SH_INFO_MAX_VEC];
+};
+
+struct xen_pci_sharedinfo {
@@ -133336,17 +203179,38 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/pciif.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/protocols.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/protocols.h
---- linux-2.6.18.8/include/xen/interface/io/protocols.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/protocols.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,21 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/protocols.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/protocols.h
+--- linux-2.6.18.8/include/xen/interface/io/protocols.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/protocols.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,40 @@
++/******************************************************************************
++ * protocols.h
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
+#ifndef __XEN_PROTOCOLS_H__
+#define __XEN_PROTOCOLS_H__
+
+#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi"
+#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi"
+#define XEN_IO_PROTO_ABI_IA64 "ia64-abi"
-+#define XEN_IO_PROTO_ABI_POWERPC64 "powerpc64-abi"
+
+#if defined(__i386__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
@@ -133354,17 +203218,15 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/protocols.h linux-2.6.18-xen-
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
+#elif defined(__ia64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64
-+#elif defined(__powerpc64__)
-+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64
+#else
+# error arch fixup needed here
+#endif
+
+#endif
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/ring.h
---- linux-2.6.18.8/include/xen/interface/io/ring.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/ring.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,299 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/ring.h
+--- linux-2.6.18.8/include/xen/interface/io/ring.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/ring.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,307 @@
+/******************************************************************************
+ * ring.h
+ *
@@ -133394,6 +203256,14 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.2.0
+#ifndef __XEN_PUBLIC_IO_RING_H__
+#define __XEN_PUBLIC_IO_RING_H__
+
++#include "../xen-compat.h"
++
++#if __XEN_INTERFACE_VERSION__ < 0x00030208
++#define xen_mb() mb()
++#define xen_rmb() rmb()
++#define xen_wmb() wmb()
++#endif
++
+typedef unsigned int RING_IDX;
+
+/* Round a 32-bit unsigned constant down to the nearest power of two. */
@@ -133578,12 +203448,12 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.2.0
+ (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
+
+#define RING_PUSH_REQUESTS(_r) do { \
-+ wmb(); /* back sees requests /before/ updated producer index */ \
++ xen_wmb(); /* back sees requests /before/ updated producer index */ \
+ (_r)->sring->req_prod = (_r)->req_prod_pvt; \
+} while (0)
+
+#define RING_PUSH_RESPONSES(_r) do { \
-+ wmb(); /* front sees responses /before/ updated producer index */ \
++ xen_wmb(); /* front sees resps /before/ updated producer index */ \
+ (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
+} while (0)
+
@@ -133620,9 +203490,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.2.0
+#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \
+ RING_IDX __old = (_r)->sring->req_prod; \
+ RING_IDX __new = (_r)->req_prod_pvt; \
-+ wmb(); /* back sees requests /before/ updated producer index */ \
++ xen_wmb(); /* back sees requests /before/ updated producer index */ \
+ (_r)->sring->req_prod = __new; \
-+ mb(); /* back sees new requests /before/ we check req_event */ \
++ xen_mb(); /* back sees new requests /before/ we check req_event */ \
+ (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \
+ (RING_IDX)(__new - __old)); \
+} while (0)
@@ -133630,9 +203500,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.2.0
+#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \
+ RING_IDX __old = (_r)->sring->rsp_prod; \
+ RING_IDX __new = (_r)->rsp_prod_pvt; \
-+ wmb(); /* front sees responses /before/ updated producer index */ \
++ xen_wmb(); /* front sees resps /before/ updated producer index */ \
+ (_r)->sring->rsp_prod = __new; \
-+ mb(); /* front sees new responses /before/ we check rsp_event */ \
++ xen_mb(); /* front sees new resps /before/ we check rsp_event */ \
+ (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \
+ (RING_IDX)(__new - __old)); \
+} while (0)
@@ -133641,7 +203511,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.2.0
+ (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
+ if (_work_to_do) break; \
+ (_r)->sring->req_event = (_r)->req_cons + 1; \
-+ mb(); \
++ xen_mb(); \
+ (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
+} while (0)
+
@@ -133649,7 +203519,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.2.0
+ (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
+ if (_work_to_do) break; \
+ (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \
-+ mb(); \
++ xen_mb(); \
+ (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
+} while (0)
+
@@ -133664,9 +203534,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/ring.h linux-2.6.18-xen-3.2.0
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/tpmif.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/tpmif.h
---- linux-2.6.18.8/include/xen/interface/io/tpmif.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/tpmif.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/tpmif.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/tpmif.h
+--- linux-2.6.18.8/include/xen/interface/io/tpmif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/tpmif.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,77 @@
+/******************************************************************************
+ * tpmif.h
@@ -133745,10 +203615,119 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/tpmif.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/xenbus.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/xenbus.h
---- linux-2.6.18.8/include/xen/interface/io/xenbus.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/xenbus.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,73 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/vscsiif.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/vscsiif.h
+--- linux-2.6.18.8/include/xen/interface/io/vscsiif.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/vscsiif.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,105 @@
++/******************************************************************************
++ * vscsiif.h
++ *
++ * Based on the blkif.h code.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Copyright(c) FUJITSU Limited 2008.
++ */
++
++#ifndef __XEN__PUBLIC_IO_SCSI_H__
++#define __XEN__PUBLIC_IO_SCSI_H__
++
++#include "ring.h"
++#include "../grant_table.h"
++
++/* command between backend and frontend */
++#define VSCSIIF_ACT_SCSI_CDB 1 /* SCSI CDB command */
++#define VSCSIIF_ACT_SCSI_ABORT 2 /* SCSI Device(Lun) Abort*/
++#define VSCSIIF_ACT_SCSI_RESET 3 /* SCSI Device(Lun) Reset*/
++
++
++#define VSCSIIF_BACK_MAX_PENDING_REQS 128
++
++/*
++ * Maximum scatter/gather segments per request.
++ *
++ * Considering balance between allocating al least 16 "vscsiif_request"
++ * structures on one page (4096bytes) and number of scatter gather
++ * needed, we decided to use 26 as a magic number.
++ */
++#define VSCSIIF_SG_TABLESIZE 26
++
++/*
++ * base on linux kernel 2.6.18
++ */
++#define VSCSIIF_MAX_COMMAND_SIZE 16
++#define VSCSIIF_SENSE_BUFFERSIZE 96
++
++
++struct vscsiif_request {
++ uint16_t rqid; /* private guest value, echoed in resp */
++ uint8_t act; /* command between backend and frontend */
++ uint8_t cmd_len;
++
++ uint8_t cmnd[VSCSIIF_MAX_COMMAND_SIZE];
++ uint16_t timeout_per_command; /* The command is issued by twice
++ the value in Backend. */
++ uint16_t channel, id, lun;
++ uint16_t padding;
++ uint8_t sc_data_direction; /* for DMA_TO_DEVICE(1)
++ DMA_FROM_DEVICE(2)
++ DMA_NONE(3) requests */
++ uint8_t nr_segments; /* Number of pieces of scatter-gather */
++
++ struct scsiif_request_segment {
++ grant_ref_t gref;
++ uint16_t offset;
++ uint16_t length;
++ } seg[VSCSIIF_SG_TABLESIZE];
++ uint32_t reserved[3];
++};
++typedef struct vscsiif_request vscsiif_request_t;
++
++struct vscsiif_response {
++ uint16_t rqid;
++ uint8_t padding;
++ uint8_t sense_len;
++ uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE];
++ int32_t rslt;
++ uint32_t residual_len; /* request bufflen -
++ return the value from physical device */
++ uint32_t reserved[36];
++};
++typedef struct vscsiif_response vscsiif_response_t;
++
++DEFINE_RING_TYPES(vscsiif, struct vscsiif_request, struct vscsiif_response);
++
++
++#endif /*__XEN__PUBLIC_IO_SCSI_H__*/
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/xenbus.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/xenbus.h
+--- linux-2.6.18.8/include/xen/interface/io/xenbus.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/xenbus.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * xenbus.h
+ *
@@ -133807,7 +203786,14 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/xenbus.h linux-2.6.18-xen-3.2
+ */
+ XenbusStateClosing = 5,
+
-+ XenbusStateClosed = 6
++ XenbusStateClosed = 6,
++
++ /*
++ * Reconfiguring: The device is being reconfigured.
++ */
++ XenbusStateReconfiguring = 7,
++
++ XenbusStateReconfigured = 8
+};
+typedef enum xenbus_state XenbusState;
+
@@ -133822,10 +203808,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/xenbus.h linux-2.6.18-xen-3.2
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/io/xs_wire.h linux-2.6.18-xen-3.2.0/include/xen/interface/io/xs_wire.h
---- linux-2.6.18.8/include/xen/interface/io/xs_wire.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/io/xs_wire.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,128 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/io/xs_wire.h linux-2.6.18-xen-3.3.0/include/xen/interface/io/xs_wire.h
+--- linux-2.6.18.8/include/xen/interface/io/xs_wire.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/io/xs_wire.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,130 @@
+/*
+ * Details of the "wire" protocol between Xen Store Daemon and client
+ * library or guest kernel.
@@ -133874,7 +203860,8 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/xs_wire.h linux-2.6.18-xen-3.
+ XS_WATCH_EVENT,
+ XS_ERROR,
+ XS_IS_DOMAIN_INTRODUCED,
-+ XS_RESUME
++ XS_RESUME,
++ XS_SET_TARGET
+};
+
+#define XS_WRITE_NONE "NONE"
@@ -133888,6 +203875,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/xs_wire.h linux-2.6.18-xen-3.
+ const char *errstring;
+};
+#define XSD_ERROR(x) { x, #x }
++/* LINTED: static unused */
+static struct xsd_errors xsd_errors[]
+#if defined(__GNUC__)
+__attribute__((unused))
@@ -133954,13 +203942,31 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/io/xs_wire.h linux-2.6.18-xen-3.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/kexec.h linux-2.6.18-xen-3.2.0/include/xen/interface/kexec.h
---- linux-2.6.18.8/include/xen/interface/kexec.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/kexec.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,140 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/kexec.h linux-2.6.18-xen-3.3.0/include/xen/interface/kexec.h
+--- linux-2.6.18.8/include/xen/interface/kexec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/kexec.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,189 @@
+/******************************************************************************
+ * kexec.h - Public portion
+ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
+ * Xen port written by:
+ * - Simon 'Horms' Horman <horms@verge.net.au>
+ * - Magnus Damm <magnus@valinux.co.jp>
@@ -134068,9 +204074,19 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/kexec.h linux-2.6.18-xen-3.2.0/i
+ xen_kexec_image_t image;
+} xen_kexec_load_t;
+
-+#define KEXEC_RANGE_MA_CRASH 0 /* machine address and size of crash area */
-+#define KEXEC_RANGE_MA_XEN 1 /* machine address and size of Xen itself */
-+#define KEXEC_RANGE_MA_CPU 2 /* machine address and size of a CPU note */
++#define KEXEC_RANGE_MA_CRASH 0 /* machine address and size of crash area */
++#define KEXEC_RANGE_MA_XEN 1 /* machine address and size of Xen itself */
++#define KEXEC_RANGE_MA_CPU 2 /* machine address and size of a CPU note */
++#define KEXEC_RANGE_MA_XENHEAP 3 /* machine address and size of xenheap
++ * Note that although this is adjacent
++ * to Xen it exists in a separate EFI
++ * region on ia64, and thus needs to be
++ * inserted into iomem_machine separately */
++#define KEXEC_RANGE_MA_BOOT_PARAM 4 /* machine address and size of
++ * the ia64_boot_param */
++#define KEXEC_RANGE_MA_EFI_MEMMAP 5 /* machine address and size of
++ * of the EFI Memory Map */
++#define KEXEC_RANGE_MA_VMCOREINFO 6 /* machine address and size of vmcoreinfo */
+
+/*
+ * Find the address and size of certain memory areas
@@ -134087,6 +204103,27 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/kexec.h linux-2.6.18-xen-3.2.0/i
+ unsigned long start;
+} xen_kexec_range_t;
+
++/* vmcoreinfo stuff */
++#define VMCOREINFO_BYTES (4096)
++#define VMCOREINFO_NOTE_NAME "VMCOREINFO_XEN"
++void arch_crash_save_vmcoreinfo(void);
++void vmcoreinfo_append_str(const char *fmt, ...)
++ __attribute__ ((format (printf, 1, 2)));
++#define VMCOREINFO_PAGESIZE(value) \
++ vmcoreinfo_append_str("PAGESIZE=%ld\n", value)
++#define VMCOREINFO_SYMBOL(name) \
++ vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
++#define VMCOREINFO_SYMBOL_ALIAS(alias, name) \
++ vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #alias, (unsigned long)&name)
++#define VMCOREINFO_STRUCT_SIZE(name) \
++ vmcoreinfo_append_str("SIZE(%s)=%zu\n", #name, sizeof(struct name))
++#define VMCOREINFO_OFFSET(name, field) \
++ vmcoreinfo_append_str("OFFSET(%s.%s)=%lu\n", #name, #field, \
++ (unsigned long)offsetof(struct name, field))
++#define VMCOREINFO_OFFSET_ALIAS(name, field, alias) \
++ vmcoreinfo_append_str("OFFSET(%s.%s)=%lu\n", #name, #alias, \
++ (unsigned long)offsetof(struct name, field))
++
+#endif /* _XEN_PUBLIC_KEXEC_H */
+
+/*
@@ -134098,17 +204135,37 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/kexec.h linux-2.6.18-xen-3.2.0/i
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/libelf.h linux-2.6.18-xen-3.2.0/include/xen/interface/libelf.h
---- linux-2.6.18.8/include/xen/interface/libelf.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/libelf.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,245 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/libelf.h linux-2.6.18-xen-3.3.0/include/xen/interface/libelf.h
+--- linux-2.6.18.8/include/xen/interface/libelf.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/libelf.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,265 @@
++/******************************************************************************
++ * libelf.h
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
+#ifndef __XC_LIBELF__
+#define __XC_LIBELF__ 1
+
-+#if defined(__i386__) || defined(__x86_64) || defined(__ia64__)
++#if defined(__i386__) || defined(__x86_64__) || defined(__ia64__)
+#define XEN_ELF_LITTLE_ENDIAN
-+#elif defined(__powerpc__)
-+#define XEN_ELF_BIG_ENDIAN
+#else
+#error define architectural endianness
+#endif
@@ -134347,10 +204404,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/libelf.h linux-2.6.18-xen-3.2.0/
+ struct elf_dom_parms *parms);
+
+#endif /* __XC_LIBELF__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/memory.h linux-2.6.18-xen-3.2.0/include/xen/interface/memory.h
---- linux-2.6.18.8/include/xen/interface/memory.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/memory.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,281 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/memory.h linux-2.6.18-xen-3.3.0/include/xen/interface/memory.h
+--- linux-2.6.18.8/include/xen/interface/memory.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/memory.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,295 @@
+/******************************************************************************
+ * memory.h
+ *
@@ -134388,6 +204445,21 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/memory.h linux-2.6.18-xen-3.2.0/
+#define XENMEM_increase_reservation 0
+#define XENMEM_decrease_reservation 1
+#define XENMEM_populate_physmap 6
++
++#if __XEN_INTERFACE_VERSION__ >= 0x00030209
++/*
++ * Maximum # bits addressable by the user of the allocated region (e.g., I/O
++ * devices often have a 32-bit limitation even in 64-bit systems). If zero
++ * then the user has no addressing restriction. This field is not used by
++ * XENMEM_decrease_reservation.
++ */
++#define XENMEMF_address_bits(x) (x)
++#define XENMEMF_get_address_bits(x) ((x) & 0xffu)
++/* NUMA node to allocate from. */
++#define XENMEMF_node(x) (((x) + 1) << 8)
++#define XENMEMF_get_node(x) ((((x) >> 8) - 1) & 0xffu)
++#endif
++
+struct xen_memory_reservation {
+
+ /*
@@ -134406,13 +204478,12 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/memory.h linux-2.6.18-xen-3.2.0/
+ xen_ulong_t nr_extents;
+ unsigned int extent_order;
+
-+ /*
-+ * Maximum # bits addressable by the user of the allocated region (e.g.,
-+ * I/O devices often have a 32-bit limitation even in 64-bit systems). If
-+ * zero then the user has no addressing restriction.
-+ * This field is not used by XENMEM_decrease_reservation.
-+ */
++#if __XEN_INTERFACE_VERSION__ >= 0x00030209
++ /* XENMEMF flags. */
++ unsigned int mem_flags;
++#else
+ unsigned int address_bits;
++#endif
+
+ /*
+ * Domain whose reservation is being changed.
@@ -134632,9 +204703,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/memory.h linux-2.6.18-xen-3.2.0/
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/nmi.h linux-2.6.18-xen-3.2.0/include/xen/interface/nmi.h
---- linux-2.6.18.8/include/xen/interface/nmi.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/nmi.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/nmi.h linux-2.6.18-xen-3.3.0/include/xen/interface/nmi.h
+--- linux-2.6.18.8/include/xen/interface/nmi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/nmi.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,78 @@
+/******************************************************************************
+ * nmi.h
@@ -134714,10 +204785,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/nmi.h linux-2.6.18-xen-3.2.0/inc
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/physdev.h linux-2.6.18-xen-3.2.0/include/xen/interface/physdev.h
---- linux-2.6.18.8/include/xen/interface/physdev.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/physdev.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,169 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/physdev.h linux-2.6.18-xen-3.3.0/include/xen/interface/physdev.h
+--- linux-2.6.18.8/include/xen/interface/physdev.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/physdev.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,219 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
@@ -134801,7 +204872,11 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/physdev.h linux-2.6.18-xen-3.2.0
+#define PHYSDEVOP_set_iobitmap 7
+struct physdev_set_iobitmap {
+ /* IN */
-+ XEN_GUEST_HANDLE_00030205(uint8) bitmap;
++#if __XEN_INTERFACE_VERSION__ >= 0x00030205
++ XEN_GUEST_HANDLE(uint8) bitmap;
++#else
++ uint8_t *bitmap;
++#endif
+ uint32_t nr_ports;
+};
+typedef struct physdev_set_iobitmap physdev_set_iobitmap_t;
@@ -134837,6 +204912,52 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/physdev.h linux-2.6.18-xen-3.2.0
+};
+typedef struct physdev_irq physdev_irq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
++
++#define MAP_PIRQ_TYPE_MSI 0x0
++#define MAP_PIRQ_TYPE_GSI 0x1
++#define MAP_PIRQ_TYPE_UNKNOWN 0x2
++
++#define PHYSDEVOP_map_pirq 13
++struct physdev_map_pirq {
++ domid_t domid;
++ /* IN */
++ int type;
++ /* IN */
++ int index;
++ /* IN or OUT */
++ int pirq;
++ /* IN */
++ int bus;
++ /* IN */
++ int devfn;
++ /* IN */
++ int entry_nr;
++ /* IN */
++ uint64_t table_base;
++};
++typedef struct physdev_map_pirq physdev_map_pirq_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);
++
++#define PHYSDEVOP_unmap_pirq 14
++struct physdev_unmap_pirq {
++ domid_t domid;
++ /* IN */
++ int pirq;
++};
++
++typedef struct physdev_unmap_pirq physdev_unmap_pirq_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_unmap_pirq_t);
++
++#define PHYSDEVOP_manage_pci_add 15
++#define PHYSDEVOP_manage_pci_remove 16
++struct physdev_manage_pci {
++ /* IN */
++ uint8_t bus;
++ uint8_t devfn;
++};
++
++typedef struct physdev_manage_pci physdev_manage_pci_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t);
+
+/*
+ * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
@@ -134887,10 +205008,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/physdev.h linux-2.6.18-xen-3.2.0
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/platform.h linux-2.6.18-xen-3.2.0/include/xen/interface/platform.h
---- linux-2.6.18.8/include/xen/interface/platform.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/platform.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,232 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/platform.h linux-2.6.18-xen-3.3.0/include/xen/interface/platform.h
+--- linux-2.6.18.8/include/xen/interface/platform.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/platform.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,346 @@
+/******************************************************************************
+ * platform.h
+ *
@@ -135092,6 +205213,119 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/platform.h linux-2.6.18-xen-3.2.
+typedef struct xenpf_getidletime xenpf_getidletime_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
+
++#define XENPF_set_processor_pminfo 54
++
++/* ability bits */
++#define XEN_PROCESSOR_PM_CX 1
++#define XEN_PROCESSOR_PM_PX 2
++#define XEN_PROCESSOR_PM_TX 4
++
++/* cmd type */
++#define XEN_PM_CX 0
++#define XEN_PM_PX 1
++#define XEN_PM_TX 2
++
++/* Px sub info type */
++#define XEN_PX_PCT 1
++#define XEN_PX_PSS 2
++#define XEN_PX_PPC 4
++#define XEN_PX_PSD 8
++
++struct xen_power_register {
++ uint32_t space_id;
++ uint32_t bit_width;
++ uint32_t bit_offset;
++ uint32_t access_size;
++ uint64_t address;
++};
++
++struct xen_processor_csd {
++ uint32_t domain; /* domain number of one dependent group */
++ uint32_t coord_type; /* coordination type */
++ uint32_t num; /* number of processors in same domain */
++};
++typedef struct xen_processor_csd xen_processor_csd_t;
++DEFINE_XEN_GUEST_HANDLE(xen_processor_csd_t);
++
++struct xen_processor_cx {
++ struct xen_power_register reg; /* GAS for Cx trigger register */
++ uint8_t type; /* cstate value, c0: 0, c1: 1, ... */
++ uint32_t latency; /* worst latency (ms) to enter/exit this cstate */
++ uint32_t power; /* average power consumption(mW) */
++ uint32_t dpcnt; /* number of dependency entries */
++ XEN_GUEST_HANDLE(xen_processor_csd_t) dp; /* NULL if no dependency */
++};
++typedef struct xen_processor_cx xen_processor_cx_t;
++DEFINE_XEN_GUEST_HANDLE(xen_processor_cx_t);
++
++struct xen_processor_flags {
++ uint32_t bm_control:1;
++ uint32_t bm_check:1;
++ uint32_t has_cst:1;
++ uint32_t power_setup_done:1;
++ uint32_t bm_rld_set:1;
++};
++
++struct xen_processor_power {
++ uint32_t count; /* number of C state entries in array below */
++ struct xen_processor_flags flags; /* global flags of this processor */
++ XEN_GUEST_HANDLE(xen_processor_cx_t) states; /* supported c states */
++};
++
++struct xen_pct_register {
++ uint8_t descriptor;
++ uint16_t length;
++ uint8_t space_id;
++ uint8_t bit_width;
++ uint8_t bit_offset;
++ uint8_t reserved;
++ uint64_t address;
++};
++
++struct xen_processor_px {
++ uint64_t core_frequency; /* megahertz */
++ uint64_t power; /* milliWatts */
++ uint64_t transition_latency; /* microseconds */
++ uint64_t bus_master_latency; /* microseconds */
++ uint64_t control; /* control value */
++ uint64_t status; /* success indicator */
++};
++typedef struct xen_processor_px xen_processor_px_t;
++DEFINE_XEN_GUEST_HANDLE(xen_processor_px_t);
++
++struct xen_psd_package {
++ uint64_t num_entries;
++ uint64_t revision;
++ uint64_t domain;
++ uint64_t coord_type;
++ uint64_t num_processors;
++};
++
++struct xen_processor_performance {
++ uint32_t flags; /* flag for Px sub info type */
++ uint32_t ppc; /* Platform limitation on freq usage */
++ struct xen_pct_register control_register;
++ struct xen_pct_register status_register;
++ uint32_t state_count; /* total available performance states */
++ XEN_GUEST_HANDLE(xen_processor_px_t) states;
++ struct xen_psd_package domain_info;
++ uint32_t shared_type; /* coordination type of this processor */
++};
++typedef struct xen_processor_performance xen_processor_performance_t;
++DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t);
++
++struct xenpf_set_processor_pminfo {
++ /* IN variables */
++ uint32_t id; /* ACPI CPU ID */
++ uint32_t type; /* {XEN_PM_CX, XEN_PM_PX} */
++ union {
++ struct xen_processor_power power;/* Cx: _CST/_CSD */
++ struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */
++ };
++};
++typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
++
+struct xen_platform_op {
+ uint32_t cmd;
+ uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -135106,6 +205340,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/platform.h linux-2.6.18-xen-3.2.
+ struct xenpf_enter_acpi_sleep enter_acpi_sleep;
+ struct xenpf_change_freq change_freq;
+ struct xenpf_getidletime getidletime;
++ struct xenpf_set_processor_pminfo set_pminfo;
+ uint8_t pad[128];
+ } u;
+};
@@ -135123,9 +205358,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/platform.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/sched.h linux-2.6.18-xen-3.2.0/include/xen/interface/sched.h
---- linux-2.6.18.8/include/xen/interface/sched.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/sched.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/sched.h linux-2.6.18-xen-3.3.0/include/xen/interface/sched.h
+--- linux-2.6.18.8/include/xen/interface/sched.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/sched.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,121 @@
+/******************************************************************************
+ * sched.h
@@ -135248,10 +205483,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/sched.h linux-2.6.18-xen-3.2.0/i
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/sysctl.h linux-2.6.18-xen-3.2.0/include/xen/interface/sysctl.h
---- linux-2.6.18.8/include/xen/interface/sysctl.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/sysctl.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,238 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/sysctl.h linux-2.6.18-xen-3.3.0/include/xen/interface/sysctl.h
+--- linux-2.6.18.8/include/xen/interface/sysctl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/sysctl.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,295 @@
+/******************************************************************************
+ * sysctl.h
+ *
@@ -135338,8 +205573,13 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/sysctl.h linux-2.6.18-xen-3.2.0/
+ * Get physical information about the host machine
+ */
+#define XEN_SYSCTL_physinfo 3
++ /* (x86) The platform supports HVM guests. */
++#define _XEN_SYSCTL_PHYSCAP_hvm 0
++#define XEN_SYSCTL_PHYSCAP_hvm (1u<<_XEN_SYSCTL_PHYSCAP_hvm)
++ /* (x86) The platform supports HVM-guest direct access to I/O devices. */
++#define _XEN_SYSCTL_PHYSCAP_hvm_directio 1
++#define XEN_SYSCTL_PHYSCAP_hvm_directio (1u<<_XEN_SYSCTL_PHYSCAP_hvm_directio)
+struct xen_sysctl_physinfo {
-+ /* IN variables. */
+ uint32_t threads_per_core;
+ uint32_t cores_per_socket;
+ uint32_t nr_cpus;
@@ -135350,7 +205590,6 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/sysctl.h linux-2.6.18-xen-3.2.0/
+ uint64_aligned_t scrub_pages;
+ uint32_t hw_cap[8];
+
-+ /* IN/OUT variables. */
+ /*
+ * IN: maximum addressable entry in the caller-provided cpu_to_node array.
+ * OUT: largest cpu identifier in the system.
@@ -135366,6 +205605,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/sysctl.h linux-2.6.18-xen-3.2.0/
+ * elements of the array will not be written by the sysctl.
+ */
+ XEN_GUEST_HANDLE_64(uint32) cpu_to_node;
++
++ /* XEN_SYSCTL_PHYSCAP_??? */
++ uint32_t capabilities;
+};
+typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t);
@@ -135459,7 +205701,56 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/sysctl.h linux-2.6.18-xen-3.2.0/
+};
+typedef struct xen_sysctl_availheap xen_sysctl_availheap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_availheap_t);
-+
++
++#define XEN_SYSCTL_get_pmstat 10
++struct pm_px_val {
++ uint64_aligned_t freq; /* Px core frequency */
++ uint64_aligned_t residency; /* Px residency time */
++ uint64_aligned_t count; /* Px transition count */
++};
++typedef struct pm_px_val pm_px_val_t;
++DEFINE_XEN_GUEST_HANDLE(pm_px_val_t);
++
++struct pm_px_stat {
++ uint8_t total; /* total Px states */
++ uint8_t usable; /* usable Px states */
++ uint8_t last; /* last Px state */
++ uint8_t cur; /* current Px state */
++ XEN_GUEST_HANDLE_64(uint64) trans_pt; /* Px transition table */
++ XEN_GUEST_HANDLE_64(pm_px_val_t) pt;
++};
++typedef struct pm_px_stat pm_px_stat_t;
++DEFINE_XEN_GUEST_HANDLE(pm_px_stat_t);
++
++struct pm_cx_stat {
++ uint32_t nr; /* entry nr in triggers & residencies, including C0 */
++ uint32_t last; /* last Cx state */
++ uint64_aligned_t idle_time; /* idle time from boot */
++ XEN_GUEST_HANDLE_64(uint64) triggers; /* Cx trigger counts */
++ XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */
++};
++
++struct xen_sysctl_get_pmstat {
++#define PMSTAT_CATEGORY_MASK 0xf0
++#define PMSTAT_PX 0x10
++#define PMSTAT_CX 0x20
++#define PMSTAT_get_max_px (PMSTAT_PX | 0x1)
++#define PMSTAT_get_pxstat (PMSTAT_PX | 0x2)
++#define PMSTAT_reset_pxstat (PMSTAT_PX | 0x3)
++#define PMSTAT_get_max_cx (PMSTAT_CX | 0x1)
++#define PMSTAT_get_cxstat (PMSTAT_CX | 0x2)
++#define PMSTAT_reset_cxstat (PMSTAT_CX | 0x3)
++ uint32_t type;
++ uint32_t cpuid;
++ union {
++ struct pm_px_stat getpx;
++ struct pm_cx_stat getcx;
++ /* other struct for tx, etc */
++ } u;
++};
++typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_get_pmstat_t);
++
+struct xen_sysctl {
+ uint32_t cmd;
+ uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
@@ -135473,6 +205764,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/sysctl.h linux-2.6.18-xen-3.2.0/
+ struct xen_sysctl_debug_keys debug_keys;
+ struct xen_sysctl_getcpuinfo getcpuinfo;
+ struct xen_sysctl_availheap availheap;
++ struct xen_sysctl_get_pmstat get_pmstat;
+ uint8_t pad[128];
+ } u;
+};
@@ -135490,10 +205782,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/sysctl.h linux-2.6.18-xen-3.2.0/
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/trace.h linux-2.6.18-xen-3.2.0/include/xen/interface/trace.h
---- linux-2.6.18.8/include/xen/interface/trace.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/trace.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,159 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/trace.h linux-2.6.18-xen-3.3.0/include/xen/interface/trace.h
+--- linux-2.6.18.8/include/xen/interface/trace.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/trace.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,172 @@
+/******************************************************************************
+ * include/public/trace.h
+ *
@@ -135583,21 +205875,25 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/trace.h linux-2.6.18-xen-3.2.0/i
+#define TRC_PV_PTWR_EMULATION (TRC_PV + 11)
+#define TRC_PV_PTWR_EMULATION_PAE (TRC_PV + 12)
+ /* Indicates that addresses in trace record are 64 bits */
-+#define TRC_PV_64_FLAG (0x100)
++#define TRC_64_FLAG (0x100)
+
+/* trace events per subclass */
+#define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01)
+#define TRC_HVM_VMEXIT (TRC_HVM_ENTRYEXIT + 0x02)
-+#define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + 0x03)
++#define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + 0x02)
+#define TRC_HVM_PF_XEN (TRC_HVM_HANDLER + 0x01)
++#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x01)
+#define TRC_HVM_PF_INJECT (TRC_HVM_HANDLER + 0x02)
++#define TRC_HVM_PF_INJECT64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x02)
+#define TRC_HVM_INJ_EXC (TRC_HVM_HANDLER + 0x03)
+#define TRC_HVM_INJ_VIRQ (TRC_HVM_HANDLER + 0x04)
+#define TRC_HVM_REINJ_VIRQ (TRC_HVM_HANDLER + 0x05)
+#define TRC_HVM_IO_READ (TRC_HVM_HANDLER + 0x06)
+#define TRC_HVM_IO_WRITE (TRC_HVM_HANDLER + 0x07)
+#define TRC_HVM_CR_READ (TRC_HVM_HANDLER + 0x08)
++#define TRC_HVM_CR_READ64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x08)
+#define TRC_HVM_CR_WRITE (TRC_HVM_HANDLER + 0x09)
++#define TRC_HVM_CR_WRITE64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x09)
+#define TRC_HVM_DR_READ (TRC_HVM_HANDLER + 0x0A)
+#define TRC_HVM_DR_WRITE (TRC_HVM_HANDLER + 0x0B)
+#define TRC_HVM_MSR_READ (TRC_HVM_HANDLER + 0x0C)
@@ -135609,12 +205905,13 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/trace.h linux-2.6.18-xen-3.2.0/i
+#define TRC_HVM_VMMCALL (TRC_HVM_HANDLER + 0x12)
+#define TRC_HVM_HLT (TRC_HVM_HANDLER + 0x13)
+#define TRC_HVM_INVLPG (TRC_HVM_HANDLER + 0x14)
++#define TRC_HVM_INVLPG64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x14)
+#define TRC_HVM_MCE (TRC_HVM_HANDLER + 0x15)
+#define TRC_HVM_IO_ASSIST (TRC_HVM_HANDLER + 0x16)
+#define TRC_HVM_MMIO_ASSIST (TRC_HVM_HANDLER + 0x17)
+#define TRC_HVM_CLTS (TRC_HVM_HANDLER + 0x18)
+#define TRC_HVM_LMSW (TRC_HVM_HANDLER + 0x19)
-+#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + 0x20)
++#define TRC_HVM_LMSW64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19)
+
+/* This structure represents a single trace buffer record. */
+struct t_rec {
@@ -135637,6 +205934,14 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/trace.h linux-2.6.18-xen-3.2.0/i
+ * field, indexes into an array of struct t_rec's.
+ */
+struct t_buf {
++ /* Assume the data buffer size is X. X is generally not a power of 2.
++ * CONS and PROD are incremented modulo (2*X):
++ * 0 <= cons < 2*X
++ * 0 <= prod < 2*X
++ * This is done because addition modulo X breaks at 2^32 when X is not a
++ * power of 2:
++ * (((2^32 - 1) % X) + 1) % X != (2^32) % X
++ */
+ uint32_t cons; /* Offset of next item to be consumed by control tools. */
+ uint32_t prod; /* Offset of next item to be produced by Xen. */
+ /* Records follow immediately after the meta-data header. */
@@ -135653,10 +205958,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/trace.h linux-2.6.18-xen-3.2.0/i
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/vcpu.h linux-2.6.18-xen-3.2.0/include/xen/interface/vcpu.h
---- linux-2.6.18.8/include/xen/interface/vcpu.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/vcpu.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,195 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/vcpu.h linux-2.6.18-xen-3.3.0/include/xen/interface/vcpu.h
+--- linux-2.6.18.8/include/xen/interface/vcpu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/vcpu.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,213 @@
+/******************************************************************************
+ * vcpu.h
+ *
@@ -135829,7 +206134,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/vcpu.h linux-2.6.18-xen-3.2.0/in
+ *
+ * This may be called only once per vcpu.
+ */
-+#define VCPUOP_register_vcpu_info 10 /* arg == struct vcpu_info */
++#define VCPUOP_register_vcpu_info 10 /* arg == vcpu_register_vcpu_info_t */
+struct vcpu_register_vcpu_info {
+ uint64_t mfn; /* mfn of page to place vcpu_info */
+ uint32_t offset; /* offset within page */
@@ -135841,6 +206146,24 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/vcpu.h linux-2.6.18-xen-3.2.0/in
+/* Send an NMI to the specified VCPU. @extra_arg == NULL. */
+#define VCPUOP_send_nmi 11
+
++/*
++ * Get the physical ID information for a pinned vcpu's underlying physical
++ * processor. The physical ID informmation is architecture-specific.
++ * On x86: id[31:0]=apic_id, id[63:32]=acpi_id, and all values 0xff and
++ * greater are reserved.
++ * This command returns -EINVAL if it is not a valid operation for this VCPU.
++ */
++#define VCPUOP_get_physid 12 /* arg == vcpu_get_physid_t */
++struct vcpu_get_physid {
++ uint64_t phys_id;
++};
++typedef struct vcpu_get_physid vcpu_get_physid_t;
++DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_t);
++#define xen_vcpu_physid_to_x86_apicid(physid) \
++ ((((uint32_t)(physid)) >= 0xff) ? 0xff : ((uint8_t)(physid)))
++#define xen_vcpu_physid_to_x86_acpiid(physid) \
++ ((((uint32_t)((physid)>>32)) >= 0xff) ? 0xff : ((uint8_t)((physid)>>32)))
++
+#endif /* __XEN_PUBLIC_VCPU_H__ */
+
+/*
@@ -135852,9 +206175,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/vcpu.h linux-2.6.18-xen-3.2.0/in
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/version.h linux-2.6.18-xen-3.2.0/include/xen/interface/version.h
---- linux-2.6.18.8/include/xen/interface/version.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/version.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/version.h linux-2.6.18-xen-3.3.0/include/xen/interface/version.h
+--- linux-2.6.18.8/include/xen/interface/version.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/version.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,91 @@
+/******************************************************************************
+ * version.h
@@ -135947,10 +206270,55 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/version.h linux-2.6.18-xen-3.2.0
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/xen-compat.h linux-2.6.18-xen-3.2.0/include/xen/interface/xen-compat.h
---- linux-2.6.18.8/include/xen/interface/xen-compat.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/xen-compat.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,51 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/xencomm.h linux-2.6.18-xen-3.3.0/include/xen/interface/xencomm.h
+--- linux-2.6.18.8/include/xen/interface/xencomm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/xencomm.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,41 @@
++/*
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Copyright (C) IBM Corp. 2006
++ */
++
++#ifndef _XEN_XENCOMM_H_
++#define _XEN_XENCOMM_H_
++
++/* A xencomm descriptor is a scatter/gather list containing physical
++ * addresses corresponding to a virtually contiguous memory area. The
++ * hypervisor translates these physical addresses to machine addresses to copy
++ * to and from the virtually contiguous area.
++ */
++
++#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
++#define XENCOMM_INVALID (~0UL)
++
++struct xencomm_desc {
++ uint32_t magic;
++ uint32_t nr_addrs; /* the number of entries in address[] */
++ uint64_t address[0];
++};
++
++#endif /* _XEN_XENCOMM_H_ */
+diff -rpuN linux-2.6.18.8/include/xen/interface/xen-compat.h linux-2.6.18-xen-3.3.0/include/xen/interface/xen-compat.h
+--- linux-2.6.18.8/include/xen/interface/xen-compat.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/xen-compat.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,44 @@
+/******************************************************************************
+ * xen-compat.h
+ *
@@ -135980,7 +206348,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xen-compat.h linux-2.6.18-xen-3.
+#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
+#define __XEN_PUBLIC_XEN_COMPAT_H__
+
-+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030207
++#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030209
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/* Xen is built with matching headers and implements the latest interface. */
@@ -135994,18 +206362,11 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xen-compat.h linux-2.6.18-xen-3.
+#error "These header files do not support the requested interface version."
+#endif
+
-+/* Fields defined as a Xen guest handle since 0x00030205. */
-+#if __XEN_INTERFACE_VERSION__ >= 0x00030205
-+#define XEN_GUEST_HANDLE_00030205(type) XEN_GUEST_HANDLE(type)
-+#else
-+#define XEN_GUEST_HANDLE_00030205(type) type *
-+#endif
-+
+#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/xen.h linux-2.6.18-xen-3.2.0/include/xen/interface/xen.h
---- linux-2.6.18.8/include/xen/interface/xen.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/xen.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,636 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/xen.h linux-2.6.18-xen-3.3.0/include/xen/interface/xen.h
+--- linux-2.6.18.8/include/xen/interface/xen.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/xen.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,639 @@
+/******************************************************************************
+ * xen.h
+ *
@@ -136041,8 +206402,6 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xen.h linux-2.6.18-xen-3.2.0/inc
+#include "arch-x86/xen.h"
+#elif defined(__ia64__)
+#include "arch-ia64.h"
-+#elif defined(__powerpc__)
-+#include "arch-powerpc.h"
+#else
+#error "Unsupported architecture"
+#endif
@@ -136271,7 +206630,11 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xen.h linux-2.6.18-xen-3.2.0/inc
+ /* SET_LDT */
+ unsigned int nr_ents;
+ /* TLB_FLUSH_MULTI, INVLPG_MULTI */
-+ XEN_GUEST_HANDLE_00030205(void) vcpumask;
++#if __XEN_INTERFACE_VERSION__ >= 0x00030205
++ XEN_GUEST_HANDLE(void) vcpumask;
++#else
++ void *vcpumask;
++#endif
+ } arg2;
+};
+typedef struct mmuext_op mmuext_op_t;
@@ -136560,6 +206923,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xen.h linux-2.6.18-xen-3.2.0/inc
+/* These flags are passed in the 'flags' field of start_info_t. */
+#define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */
+#define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */
++#define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */
+
+typedef struct dom0_vga_console_info {
+ uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
@@ -136642,54 +207006,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xen.h linux-2.6.18-xen-3.2.0/inc
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/xencomm.h linux-2.6.18-xen-3.2.0/include/xen/interface/xencomm.h
---- linux-2.6.18.8/include/xen/interface/xencomm.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/xencomm.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,41 @@
-+/*
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to
-+ * deal in the Software without restriction, including without limitation the
-+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-+ * sell copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ * DEALINGS IN THE SOFTWARE.
-+ *
-+ * Copyright (C) IBM Corp. 2006
-+ */
-+
-+#ifndef _XEN_XENCOMM_H_
-+#define _XEN_XENCOMM_H_
-+
-+/* A xencomm descriptor is a scatter/gather list containing physical
-+ * addresses corresponding to a virtually contiguous memory area. The
-+ * hypervisor translates these physical addresses to machine addresses to copy
-+ * to and from the virtually contiguous area.
-+ */
-+
-+#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
-+#define XENCOMM_INVALID (~0UL)
-+
-+struct xencomm_desc {
-+ uint32_t magic;
-+ uint32_t nr_addrs; /* the number of entries in address[] */
-+ uint64_t address[0];
-+};
-+
-+#endif /* _XEN_XENCOMM_H_ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/xenoprof.h linux-2.6.18-xen-3.2.0/include/xen/interface/xenoprof.h
---- linux-2.6.18.8/include/xen/interface/xenoprof.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/xenoprof.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/xenoprof.h linux-2.6.18-xen-3.3.0/include/xen/interface/xenoprof.h
+--- linux-2.6.18.8/include/xen/interface/xenoprof.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/xenoprof.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * xenoprof.h
@@ -136829,10 +207148,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xenoprof.h linux-2.6.18-xen-3.2.
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm.h linux-2.6.18-xen-3.2.0/include/xen/interface/xsm/acm.h
---- linux-2.6.18.8/include/xen/interface/xsm/acm.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/xsm/acm.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,229 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm.h linux-2.6.18-xen-3.3.0/include/xen/interface/xsm/acm.h
+--- linux-2.6.18.8/include/xen/interface/xsm/acm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/xsm/acm.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,235 @@
+/*
+ * acm.h: Xen access control module interface defintions
+ *
@@ -136926,7 +207245,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm.h linux-2.6.18-xen-3.2.0
+ * whenever the interpretation of the related
+ * policy's data structure changes
+ */
-+#define ACM_POLICY_VERSION 3
++#define ACM_POLICY_VERSION 4
+#define ACM_CHWALL_VERSION 1
+#define ACM_STE_VERSION 1
+
@@ -136937,6 +207256,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm.h linux-2.6.18-xen-3.2.0
+#define ACMHOOK_none 0
+#define ACMHOOK_sharing 1
+#define ACMHOOK_authorization 2
++#define ACMHOOK_conflictset 3
+
+/* -------security policy relevant type definitions-------- */
+
@@ -136965,6 +207285,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm.h linux-2.6.18-xen-3.2.0
+/* high-16 = version, low-16 = check magic */
+#define ACM_MAGIC 0x0001debc
+
++/* size of the SHA1 hash identifying the XML policy from which the
++ binary policy was created */
++#define ACM_SHA1_HASH_SIZE 20
++
+/* each offset in bytes from start of the struct they
+ * are part of */
+
@@ -136994,6 +207318,7 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm.h linux-2.6.18-xen-3.2.0
+ uint32_t secondary_policy_code;
+ uint32_t secondary_buffer_offset;
+ struct acm_policy_version xml_pol_version; /* add in V3 */
++ uint8_t xml_policy_hash[ACM_SHA1_HASH_SIZE]; /* added in V4 */
+};
+
+
@@ -137062,9 +207387,9 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm.h linux-2.6.18-xen-3.2.0
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm_ops.h linux-2.6.18-xen-3.2.0/include/xen/interface/xsm/acm_ops.h
---- linux-2.6.18.8/include/xen/interface/xsm/acm_ops.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/xsm/acm_ops.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm_ops.h linux-2.6.18-xen-3.3.0/include/xen/interface/xsm/acm_ops.h
+--- linux-2.6.18.8/include/xen/interface/xsm/acm_ops.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/xsm/acm_ops.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,159 @@
+/*
+ * acm_ops.h: Xen access control module hypervisor commands
@@ -137225,10 +207550,10 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/acm_ops.h linux-2.6.18-xen-3
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/flask_op.h linux-2.6.18-xen-3.2.0/include/xen/interface/xsm/flask_op.h
---- linux-2.6.18.8/include/xen/interface/xsm/flask_op.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/interface/xsm/flask_op.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,43 @@
+diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/flask_op.h linux-2.6.18-xen-3.3.0/include/xen/interface/xsm/flask_op.h
+--- linux-2.6.18.8/include/xen/interface/xsm/flask_op.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/interface/xsm/flask_op.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,45 @@
+/*
+ * This file contains the flask_op hypercall commands and definitions.
+ *
@@ -137263,18 +207588,20 @@ diff -rpuN linux-2.6.18.8/include/xen/interface/xsm/flask_op.h linux-2.6.18-xen-
+#define FLASK_AVC_CACHESTATS 19
+#define FLASK_MEMBER 20
+
++#define FLASK_LAST FLASK_MEMBER
++
+typedef struct flask_op {
-+ int cmd;
-+ int size;
-+ char *buf;
++ uint32_t cmd;
++ uint32_t size;
++ char *buf;
+} flask_op_t;
+
+DEFINE_XEN_GUEST_HANDLE(flask_op_t);
+
+#endif
-diff -rpuN linux-2.6.18.8/include/xen/pcifront.h linux-2.6.18-xen-3.2.0/include/xen/pcifront.h
---- linux-2.6.18.8/include/xen/pcifront.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/pcifront.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/pcifront.h linux-2.6.18-xen-3.3.0/include/xen/pcifront.h
+--- linux-2.6.18.8/include/xen/pcifront.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/pcifront.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+ * PCI Frontend - arch-dependendent declarations
@@ -137359,9 +207686,9 @@ diff -rpuN linux-2.6.18.8/include/xen/pcifront.h linux-2.6.18-xen-3.2.0/include/
+#endif /* __KERNEL__ */
+
+#endif /* __XEN_ASM_PCIFRONT_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/public/evtchn.h linux-2.6.18-xen-3.2.0/include/xen/public/evtchn.h
---- linux-2.6.18.8/include/xen/public/evtchn.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/public/evtchn.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/public/evtchn.h linux-2.6.18-xen-3.3.0/include/xen/public/evtchn.h
+--- linux-2.6.18.8/include/xen/public/evtchn.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/public/evtchn.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * evtchn.h
@@ -137451,10 +207778,10 @@ diff -rpuN linux-2.6.18.8/include/xen/public/evtchn.h linux-2.6.18-xen-3.2.0/inc
+ _IOC(_IOC_NONE, 'E', 5, 0)
+
+#endif /* __LINUX_PUBLIC_EVTCHN_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/public/gntdev.h linux-2.6.18-xen-3.2.0/include/xen/public/gntdev.h
---- linux-2.6.18.8/include/xen/public/gntdev.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/public/gntdev.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,105 @@
+diff -rpuN linux-2.6.18.8/include/xen/public/gntdev.h linux-2.6.18-xen-3.3.0/include/xen/public/gntdev.h
+--- linux-2.6.18.8/include/xen/public/gntdev.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/public/gntdev.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,119 @@
+/******************************************************************************
+ * gntdev.h
+ *
@@ -137559,10 +207886,24 @@ diff -rpuN linux-2.6.18.8/include/xen/public/gntdev.h linux-2.6.18-xen-3.2.0/inc
+ uint32_t pad;
+};
+
++/*
++ * Sets the maximum number of grants that may mapped at once by this gntdev
++ * instance.
++ *
++ * N.B. This must be called before any other ioctl is performed on the device.
++ */
++#define IOCTL_GNTDEV_SET_MAX_GRANTS \
++_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants))
++struct ioctl_gntdev_set_max_grants {
++ /* IN parameter */
++ /* The maximum number of grants that may be mapped at once. */
++ uint32_t count;
++};
++
+#endif /* __LINUX_PUBLIC_GNTDEV_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/public/privcmd.h linux-2.6.18-xen-3.2.0/include/xen/public/privcmd.h
---- linux-2.6.18.8/include/xen/public/privcmd.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/public/privcmd.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/public/privcmd.h linux-2.6.18-xen-3.3.0/include/xen/public/privcmd.h
+--- linux-2.6.18.8/include/xen/public/privcmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/public/privcmd.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,79 @@
+/******************************************************************************
+ * privcmd.h
@@ -137643,25 +207984,9 @@ diff -rpuN linux-2.6.18.8/include/xen/public/privcmd.h linux-2.6.18-xen-3.2.0/in
+ _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
+
+#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/xen_proc.h linux-2.6.18-xen-3.2.0/include/xen/xen_proc.h
---- linux-2.6.18.8/include/xen/xen_proc.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/xen_proc.h 2008-02-15 16:22:15.000000000 -0800
-@@ -0,0 +1,12 @@
-+
-+#ifndef __ASM_XEN_PROC_H__
-+#define __ASM_XEN_PROC_H__
-+
-+#include <linux/proc_fs.h>
-+
-+extern struct proc_dir_entry *create_xen_proc_entry(
-+ const char *name, mode_t mode);
-+extern void remove_xen_proc_entry(
-+ const char *name);
-+
-+#endif /* __ASM_XEN_PROC_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/xenbus.h linux-2.6.18-xen-3.2.0/include/xen/xenbus.h
---- linux-2.6.18.8/include/xen/xenbus.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/xenbus.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/xenbus.h linux-2.6.18-xen-3.3.0/include/xen/xenbus.h
+--- linux-2.6.18.8/include/xen/xenbus.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/xenbus.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,307 @@
+/******************************************************************************
+ * xenbus.h
@@ -137970,9 +208295,9 @@ diff -rpuN linux-2.6.18.8/include/xen/xenbus.h linux-2.6.18-xen-3.2.0/include/xe
+int xenbus_for_each_frontend(void *arg, int (*fn)(struct device *, void *));
+
+#endif /* _XEN_XENBUS_H */
-diff -rpuN linux-2.6.18.8/include/xen/xencomm.h linux-2.6.18-xen-3.2.0/include/xen/xencomm.h
---- linux-2.6.18.8/include/xen/xencomm.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/xencomm.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/xencomm.h linux-2.6.18-xen-3.3.0/include/xen/xencomm.h
+--- linux-2.6.18.8/include/xen/xencomm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/xencomm.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,77 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@@ -138051,9 +208376,9 @@ diff -rpuN linux-2.6.18.8/include/xen/xencomm.h linux-2.6.18-xen-3.2.0/include/x
+#define xen_guest_handle(hnd) ((hnd).p)
+
+#endif /* _LINUX_XENCOMM_H_ */
-diff -rpuN linux-2.6.18.8/include/xen/xencons.h linux-2.6.18-xen-3.2.0/include/xen/xencons.h
---- linux-2.6.18.8/include/xen/xencons.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/xencons.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/xencons.h linux-2.6.18-xen-3.3.0/include/xen/xencons.h
+--- linux-2.6.18.8/include/xen/xencons.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/xencons.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,17 @@
+#ifndef __ASM_XENCONS_H__
+#define __ASM_XENCONS_H__
@@ -138072,9 +208397,9 @@ diff -rpuN linux-2.6.18.8/include/xen/xencons.h linux-2.6.18-xen-3.2.0/include/x
+int xencons_ring_send(const char *data, unsigned len);
+
+#endif /* __ASM_XENCONS_H__ */
-diff -rpuN linux-2.6.18.8/include/xen/xenoprof.h linux-2.6.18-xen-3.2.0/include/xen/xenoprof.h
---- linux-2.6.18.8/include/xen/xenoprof.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/include/xen/xenoprof.h 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/xenoprof.h linux-2.6.18-xen-3.3.0/include/xen/xenoprof.h
+--- linux-2.6.18.8/include/xen/xenoprof.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/xenoprof.h 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * xen/xenoprof.h
@@ -138118,20 +208443,25 @@ diff -rpuN linux-2.6.18.8/include/xen/xenoprof.h linux-2.6.18-xen-3.2.0/include/
+
+#endif /* CONFIG_XEN */
+#endif /* __XEN_XENOPROF_H__ */
-diff -rpuN linux-2.6.18.8/kernel/Kconfig.preempt linux-2.6.18-xen-3.2.0/kernel/Kconfig.preempt
---- linux-2.6.18.8/kernel/Kconfig.preempt 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/Kconfig.preempt 2008-02-15 16:22:15.000000000 -0800
-@@ -35,6 +35,7 @@ config PREEMPT_VOLUNTARY
-
- config PREEMPT
- bool "Preemptible Kernel (Low-Latency Desktop)"
-+ depends on !XEN
- help
- This option reduces the latency of the kernel by making
- all kernel code (that is not executing in a critical section)
-diff -rpuN linux-2.6.18.8/kernel/cpu.c linux-2.6.18-xen-3.2.0/kernel/cpu.c
---- linux-2.6.18.8/kernel/cpu.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/cpu.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/include/xen/xen_proc.h linux-2.6.18-xen-3.3.0/include/xen/xen_proc.h
+--- linux-2.6.18.8/include/xen/xen_proc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/include/xen/xen_proc.h 2008-08-21 11:36:07.000000000 +0200
+@@ -0,0 +1,12 @@
++
++#ifndef __ASM_XEN_PROC_H__
++#define __ASM_XEN_PROC_H__
++
++#include <linux/proc_fs.h>
++
++extern struct proc_dir_entry *create_xen_proc_entry(
++ const char *name, mode_t mode);
++extern void remove_xen_proc_entry(
++ const char *name);
++
++#endif /* __ASM_XEN_PROC_H__ */
+diff -rpuN linux-2.6.18.8/kernel/cpu.c linux-2.6.18-xen-3.3.0/kernel/cpu.c
+--- linux-2.6.18.8/kernel/cpu.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/cpu.c 2008-08-21 11:36:07.000000000 +0200
@@ -48,7 +48,10 @@ EXPORT_SYMBOL_GPL(lock_cpu_hotplug);
void unlock_cpu_hotplug(void)
@@ -138143,9 +208473,9 @@ diff -rpuN linux-2.6.18.8/kernel/cpu.c linux-2.6.18-xen-3.2.0/kernel/cpu.c
if (recursive_depth) {
recursive_depth--;
return;
-diff -rpuN linux-2.6.18.8/kernel/fork.c linux-2.6.18-xen-3.2.0/kernel/fork.c
---- linux-2.6.18.8/kernel/fork.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/fork.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/kernel/fork.c linux-2.6.18-xen-3.3.0/kernel/fork.c
+--- linux-2.6.18.8/kernel/fork.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/fork.c 2008-08-21 11:36:07.000000000 +0200
@@ -276,6 +276,9 @@ static inline int dup_mmap(struct mm_str
if (retval)
goto out;
@@ -138156,9 +208486,21 @@ diff -rpuN linux-2.6.18.8/kernel/fork.c linux-2.6.18-xen-3.2.0/kernel/fork.c
retval = 0;
out:
up_write(&mm->mmap_sem);
-diff -rpuN linux-2.6.18.8/kernel/irq/spurious.c linux-2.6.18-xen-3.2.0/kernel/irq/spurious.c
---- linux-2.6.18.8/kernel/irq/spurious.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/irq/spurious.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/kernel/hrtimer.c linux-2.6.18-xen-3.3.0/kernel/hrtimer.c
+--- linux-2.6.18.8/kernel/hrtimer.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/hrtimer.c 2008-08-21 11:36:07.000000000 +0200
+@@ -59,7 +59,7 @@ static ktime_t ktime_get(void)
+ *
+ * returns the time in ktime_t format
+ */
+-static ktime_t ktime_get_real(void)
++ktime_t ktime_get_real(void)
+ {
+ struct timespec now;
+
+diff -rpuN linux-2.6.18.8/kernel/irq/spurious.c linux-2.6.18-xen-3.3.0/kernel/irq/spurious.c
+--- linux-2.6.18.8/kernel/irq/spurious.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/irq/spurious.c 2008-08-21 11:36:07.000000000 +0200
@@ -139,7 +139,8 @@ void note_interrupt(unsigned int irq, st
irqreturn_t action_ret, struct pt_regs *regs)
{
@@ -138169,9 +208511,20 @@ diff -rpuN linux-2.6.18.8/kernel/irq/spurious.c linux-2.6.18-xen-3.2.0/kernel/ir
if (unlikely(action_ret != IRQ_NONE))
report_bad_irq(irq, desc, action_ret);
}
-diff -rpuN linux-2.6.18.8/kernel/kexec.c linux-2.6.18-xen-3.2.0/kernel/kexec.c
---- linux-2.6.18.8/kernel/kexec.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/kexec.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/kernel/Kconfig.preempt linux-2.6.18-xen-3.3.0/kernel/Kconfig.preempt
+--- linux-2.6.18.8/kernel/Kconfig.preempt 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/Kconfig.preempt 2008-08-21 11:36:07.000000000 +0200
+@@ -35,6 +35,7 @@ config PREEMPT_VOLUNTARY
+
+ config PREEMPT
+ bool "Preemptible Kernel (Low-Latency Desktop)"
++ depends on !XEN
+ help
+ This option reduces the latency of the kernel by making
+ all kernel code (that is not executing in a critical section)
+diff -rpuN linux-2.6.18.8/kernel/kexec.c linux-2.6.18-xen-3.3.0/kernel/kexec.c
+--- linux-2.6.18.8/kernel/kexec.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/kexec.c 2008-08-21 11:36:07.000000000 +0200
@@ -330,13 +330,26 @@ static int kimage_is_destination_range(s
return 0;
}
@@ -138398,9 +208751,9 @@ diff -rpuN linux-2.6.18.8/kernel/kexec.c linux-2.6.18-xen-3.2.0/kernel/kexec.c
/* Take the kexec_lock here to prevent sys_kexec_load
* running on one cpu from replacing the crash kernel
* we are using after a panic on a different cpu.
-diff -rpuN linux-2.6.18.8/kernel/resource.c linux-2.6.18-xen-3.2.0/kernel/resource.c
---- linux-2.6.18.8/kernel/resource.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/resource.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/kernel/resource.c linux-2.6.18-xen-3.3.0/kernel/resource.c
+--- linux-2.6.18.8/kernel/resource.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/resource.c 2008-08-21 11:36:07.000000000 +0200
@@ -36,6 +36,16 @@ struct resource iomem_resource = {
};
EXPORT_SYMBOL(iomem_resource);
@@ -138467,9 +208820,9 @@ diff -rpuN linux-2.6.18.8/kernel/resource.c linux-2.6.18-xen-3.2.0/kernel/resour
return 0;
}
__initcall(ioresources_init);
-diff -rpuN linux-2.6.18.8/kernel/softlockup.c linux-2.6.18-xen-3.2.0/kernel/softlockup.c
---- linux-2.6.18.8/kernel/softlockup.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/softlockup.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/kernel/softlockup.c linux-2.6.18-xen-3.3.0/kernel/softlockup.c
+--- linux-2.6.18.8/kernel/softlockup.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/softlockup.c 2008-08-21 11:36:07.000000000 +0200
@@ -40,6 +40,19 @@ void touch_softlockup_watchdog(void)
}
EXPORT_SYMBOL(touch_softlockup_watchdog);
@@ -138490,9 +208843,9 @@ diff -rpuN linux-2.6.18.8/kernel/softlockup.c linux-2.6.18-xen-3.2.0/kernel/soft
/*
* This callback runs from the timer interrupt, and checks
* whether the watchdog thread has hung or not:
-diff -rpuN linux-2.6.18.8/kernel/sysctl.c linux-2.6.18-xen-3.2.0/kernel/sysctl.c
---- linux-2.6.18.8/kernel/sysctl.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/sysctl.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/kernel/sysctl.c linux-2.6.18-xen-3.3.0/kernel/sysctl.c
+--- linux-2.6.18.8/kernel/sysctl.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/sysctl.c 2008-08-21 11:36:07.000000000 +0200
@@ -661,7 +661,7 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
@@ -138502,9 +208855,9 @@ diff -rpuN linux-2.6.18.8/kernel/sysctl.c linux-2.6.18-xen-3.2.0/kernel/sysctl.c
{
.ctl_name = KERN_ACPI_VIDEO_FLAGS,
.procname = "acpi_video_flags",
-diff -rpuN linux-2.6.18.8/kernel/timer.c linux-2.6.18-xen-3.2.0/kernel/timer.c
---- linux-2.6.18.8/kernel/timer.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/kernel/timer.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/kernel/timer.c linux-2.6.18-xen-3.3.0/kernel/timer.c
+--- linux-2.6.18.8/kernel/timer.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/kernel/timer.c 2008-08-21 11:36:07.000000000 +0200
@@ -485,7 +485,9 @@ unsigned long next_timer_interrupt(void)
if (hr_expires < 3)
return hr_expires + jiffies;
@@ -138516,9 +208869,9 @@ diff -rpuN linux-2.6.18.8/kernel/timer.c linux-2.6.18-xen-3.2.0/kernel/timer.c
base = __get_cpu_var(tvec_bases);
spin_lock(&base->lock);
-diff -rpuN linux-2.6.18.8/lib/Makefile linux-2.6.18-xen-3.2.0/lib/Makefile
---- linux-2.6.18.8/lib/Makefile 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/lib/Makefile 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/lib/Makefile linux-2.6.18-xen-3.3.0/lib/Makefile
+--- linux-2.6.18.8/lib/Makefile 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/lib/Makefile 2008-08-21 11:36:07.000000000 +0200
@@ -52,6 +52,9 @@ obj-$(CONFIG_SMP) += percpu_counter.o
obj-$(CONFIG_AUDIT_GENERIC) += audit.o
@@ -138529,9 +208882,9 @@ diff -rpuN linux-2.6.18.8/lib/Makefile linux-2.6.18-xen-3.2.0/lib/Makefile
hostprogs-y := gen_crc32table
clean-files := crc32table.h
-diff -rpuN linux-2.6.18.8/lib/swiotlb-xen.c linux-2.6.18-xen-3.2.0/lib/swiotlb-xen.c
---- linux-2.6.18.8/lib/swiotlb-xen.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/lib/swiotlb-xen.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/lib/swiotlb-xen.c linux-2.6.18-xen-3.3.0/lib/swiotlb-xen.c
+--- linux-2.6.18.8/lib/swiotlb-xen.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/lib/swiotlb-xen.c 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,745 @@
+/*
+ * Dynamic DMA mapping support.
@@ -139278,9 +209631,26 @@ diff -rpuN linux-2.6.18.8/lib/swiotlb-xen.c linux-2.6.18-xen-3.2.0/lib/swiotlb-x
+EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
+EXPORT_SYMBOL(swiotlb_dma_mapping_error);
+EXPORT_SYMBOL(swiotlb_dma_supported);
-diff -rpuN linux-2.6.18.8/mm/highmem.c linux-2.6.18-xen-3.2.0/mm/highmem.c
---- linux-2.6.18.8/mm/highmem.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/mm/highmem.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/MAINTAINERS linux-2.6.18-xen-3.3.0/MAINTAINERS
+--- linux-2.6.18.8/MAINTAINERS 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/MAINTAINERS 2008-08-21 11:36:07.000000000 +0200
+@@ -2558,6 +2558,13 @@ M: pfg@sgi.com
+ L: linux-ia64@vger.kernel.org
+ S: Supported
+
++SFC NETWORK DRIVER
++P: Steve Hodgson
++P: Ben Hutchings
++P: Robert Stonehouse
++M: linux-net-drivers@solarflare.com
++S: Supported
++
+ SGI VISUAL WORKSTATION 320 AND 540
+ P: Andrey Panin
+ M: pazke@donpac.ru
+diff -rpuN linux-2.6.18.8/mm/highmem.c linux-2.6.18-xen-3.3.0/mm/highmem.c
+--- linux-2.6.18.8/mm/highmem.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/mm/highmem.c 2008-08-21 11:36:07.000000000 +0200
@@ -142,6 +142,17 @@ start:
return vaddr;
}
@@ -139312,9 +209682,9 @@ diff -rpuN linux-2.6.18.8/mm/highmem.c linux-2.6.18-xen-3.2.0/mm/highmem.c
* for non-isa bounce case, just check if the bounce pfn is equal
* to or bigger than the highest pfn in the system -- in that case,
* don't waste time iterating over bio segments
-diff -rpuN linux-2.6.18.8/mm/memory.c linux-2.6.18-xen-3.2.0/mm/memory.c
---- linux-2.6.18.8/mm/memory.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/mm/memory.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/mm/memory.c linux-2.6.18-xen-3.3.0/mm/memory.c
+--- linux-2.6.18.8/mm/memory.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/mm/memory.c 2008-08-21 11:36:07.000000000 +0200
@@ -396,6 +396,12 @@ struct page *vm_normal_page(struct vm_ar
return NULL;
}
@@ -139499,9 +209869,9 @@ diff -rpuN linux-2.6.18.8/mm/memory.c linux-2.6.18-xen-3.2.0/mm/memory.c
/*
* handle_pte_fault chooses page fault handler according to an entry
* which was read non-atomically. Before making any commitment, on
-diff -rpuN linux-2.6.18.8/mm/mmap.c linux-2.6.18-xen-3.2.0/mm/mmap.c
---- linux-2.6.18.8/mm/mmap.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/mm/mmap.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/mm/mmap.c linux-2.6.18-xen-3.3.0/mm/mmap.c
+--- linux-2.6.18.8/mm/mmap.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/mm/mmap.c 2008-08-21 11:36:07.000000000 +0200
@@ -1963,6 +1963,10 @@ void exit_mmap(struct mm_struct *mm)
unsigned long nr_accounted = 0;
unsigned long end;
@@ -139513,9 +209883,9 @@ diff -rpuN linux-2.6.18.8/mm/mmap.c linux-2.6.18-xen-3.2.0/mm/mmap.c
lru_add_drain();
flush_cache_mm(mm);
tlb = tlb_gather_mmu(mm, 1);
-diff -rpuN linux-2.6.18.8/mm/mprotect.c linux-2.6.18-xen-3.2.0/mm/mprotect.c
---- linux-2.6.18.8/mm/mprotect.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/mm/mprotect.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/mm/mprotect.c linux-2.6.18-xen-3.3.0/mm/mprotect.c
+--- linux-2.6.18.8/mm/mprotect.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/mm/mprotect.c 2008-08-21 11:36:07.000000000 +0200
@@ -76,6 +76,8 @@ static inline void change_pmd_range(stru
next = pmd_addr_end(addr, end);
if (pmd_none_or_clear_bad(pmd))
@@ -139525,9 +209895,9 @@ diff -rpuN linux-2.6.18.8/mm/mprotect.c linux-2.6.18-xen-3.2.0/mm/mprotect.c
change_pte_range(mm, pmd, addr, next, newprot);
} while (pmd++, addr = next, addr != end);
}
-diff -rpuN linux-2.6.18.8/mm/page_alloc.c linux-2.6.18-xen-3.2.0/mm/page_alloc.c
---- linux-2.6.18.8/mm/page_alloc.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/mm/page_alloc.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/mm/page_alloc.c linux-2.6.18-xen-3.3.0/mm/page_alloc.c
+--- linux-2.6.18.8/mm/page_alloc.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/mm/page_alloc.c 2008-08-21 11:36:07.000000000 +0200
@@ -154,7 +154,11 @@ static void bad_page(struct page *page)
1 << PG_slab |
1 << PG_swapcache |
@@ -139593,9 +209963,9 @@ diff -rpuN linux-2.6.18.8/mm/page_alloc.c linux-2.6.18-xen-3.2.0/mm/page_alloc.c
arch_free_page(page, 0);
if (PageAnon(page))
-diff -rpuN linux-2.6.18.8/net/bridge/br_netfilter.c linux-2.6.18-xen-3.2.0/net/bridge/br_netfilter.c
---- linux-2.6.18.8/net/bridge/br_netfilter.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/net/bridge/br_netfilter.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/net/bridge/br_netfilter.c linux-2.6.18-xen-3.3.0/net/bridge/br_netfilter.c
+--- linux-2.6.18.8/net/bridge/br_netfilter.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/bridge/br_netfilter.c 2008-08-21 11:36:07.000000000 +0200
@@ -127,10 +127,10 @@ static inline struct nf_bridge_info *nf_
static inline void nf_bridge_save_header(struct sk_buff *skb)
@@ -139609,9 +209979,9 @@ diff -rpuN linux-2.6.18.8/net/bridge/br_netfilter.c linux-2.6.18-xen-3.2.0/net/b
memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
}
-diff -rpuN linux-2.6.18.8/net/bridge/netfilter/ebtables.c linux-2.6.18-xen-3.2.0/net/bridge/netfilter/ebtables.c
---- linux-2.6.18.8/net/bridge/netfilter/ebtables.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/net/bridge/netfilter/ebtables.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/net/bridge/netfilter/ebtables.c linux-2.6.18-xen-3.3.0/net/bridge/netfilter/ebtables.c
+--- linux-2.6.18.8/net/bridge/netfilter/ebtables.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/bridge/netfilter/ebtables.c 2008-08-21 11:36:07.000000000 +0200
@@ -597,7 +597,7 @@ ebt_check_entry(struct ebt_entry *e, str
struct ebt_entry_target *t;
struct ebt_target *target;
@@ -139629,9 +209999,9 @@ diff -rpuN linux-2.6.18.8/net/bridge/netfilter/ebtables.c linux-2.6.18-xen-3.2.0
target = find_target_lock(t->u.name, &ret, &ebt_mutex);
if (!target)
goto cleanup_watchers;
-diff -rpuN linux-2.6.18.8/net/core/dev.c linux-2.6.18-xen-3.2.0/net/core/dev.c
---- linux-2.6.18.8/net/core/dev.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/net/core/dev.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/net/core/dev.c linux-2.6.18-xen-3.3.0/net/core/dev.c
+--- linux-2.6.18.8/net/core/dev.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/core/dev.c 2008-08-21 11:36:07.000000000 +0200
@@ -113,11 +113,18 @@
#include <linux/wireless.h>
#include <net/iw_handler.h>
@@ -139745,9 +210115,20 @@ diff -rpuN linux-2.6.18.8/net/core/dev.c linux-2.6.18-xen-3.2.0/net/core/dev.c
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
EXPORT_SYMBOL(br_handle_frame_hook);
-diff -rpuN linux-2.6.18.8/net/core/skbuff.c linux-2.6.18-xen-3.2.0/net/core/skbuff.c
---- linux-2.6.18.8/net/core/skbuff.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/net/core/skbuff.c 2008-02-15 16:22:15.000000000 -0800
+diff -rpuN linux-2.6.18.8/net/core/neighbour.c linux-2.6.18-xen-3.3.0/net/core/neighbour.c
+--- linux-2.6.18.8/net/core/neighbour.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/core/neighbour.c 2008-08-21 11:36:07.000000000 +0200
+@@ -2679,7 +2679,6 @@ EXPORT_SYMBOL(neigh_table_clear);
+ EXPORT_SYMBOL(neigh_table_init);
+ EXPORT_SYMBOL(neigh_table_init_no_netlink);
+ EXPORT_SYMBOL(neigh_update);
+-EXPORT_SYMBOL(neigh_update_hhs);
+ EXPORT_SYMBOL(pneigh_enqueue);
+ EXPORT_SYMBOL(pneigh_lookup);
+ EXPORT_SYMBOL(neightbl_dump_info);
+diff -rpuN linux-2.6.18.8/net/core/skbuff.c linux-2.6.18-xen-3.3.0/net/core/skbuff.c
+--- linux-2.6.18.8/net/core/skbuff.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/core/skbuff.c 2008-08-21 11:36:07.000000000 +0200
@@ -240,6 +240,7 @@ struct sk_buff *alloc_skb_from_cache(kme
skb_shinfo(skb)->gso_size = 0;
skb_shinfo(skb)->gso_segs = 0;
@@ -139767,9 +210148,17 @@ diff -rpuN linux-2.6.18.8/net/core/skbuff.c linux-2.6.18-xen-3.2.0/net/core/skbu
C(pkt_type);
C(ip_summed);
C(priority);
-diff -rpuN linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.6.18-xen-3.2.0/net/ipv4/netfilter/ip_nat_proto_tcp.c
---- linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_tcp.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/net/ipv4/netfilter/ip_nat_proto_tcp.c 2008-02-15 16:22:16.000000000 -0800
+@@ -2071,7 +2076,6 @@ EXPORT_SYMBOL(pskb_copy);
+ EXPORT_SYMBOL(pskb_expand_head);
+ EXPORT_SYMBOL(skb_checksum);
+ EXPORT_SYMBOL(skb_clone);
+-EXPORT_SYMBOL(skb_clone_fraglist);
+ EXPORT_SYMBOL(skb_copy);
+ EXPORT_SYMBOL(skb_copy_and_csum_bits);
+ EXPORT_SYMBOL(skb_copy_and_csum_dev);
+diff -rpuN linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.6.18-xen-3.3.0/net/ipv4/netfilter/ip_nat_proto_tcp.c
+--- linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_tcp.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/ipv4/netfilter/ip_nat_proto_tcp.c 2008-08-21 11:36:07.000000000 +0200
@@ -129,7 +129,12 @@ tcp_manip_pkt(struct sk_buff **pskb,
if (hdrsize < sizeof(*hdr))
return 1;
@@ -139784,9 +210173,9 @@ diff -rpuN linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.6.18-xen
ip_nat_cheat_check(oldport ^ 0xFFFF,
newport,
hdr->check));
-diff -rpuN linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.6.18-xen-3.2.0/net/ipv4/netfilter/ip_nat_proto_udp.c
---- linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_udp.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/net/ipv4/netfilter/ip_nat_proto_udp.c 2008-02-15 16:22:16.000000000 -0800
+diff -rpuN linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.6.18-xen-3.3.0/net/ipv4/netfilter/ip_nat_proto_udp.c
+--- linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_udp.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/ipv4/netfilter/ip_nat_proto_udp.c 2008-08-21 11:36:07.000000000 +0200
@@ -113,11 +113,17 @@ udp_manip_pkt(struct sk_buff **pskb,
newport = tuple->dst.u.udp.port;
portptr = &hdr->dest;
@@ -139807,9 +210196,9 @@ diff -rpuN linux-2.6.18.8/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.6.18-xen
*portptr = newport;
return 1;
}
-diff -rpuN linux-2.6.18.8/net/ipv4/tcp_input.c linux-2.6.18-xen-3.2.0/net/ipv4/tcp_input.c
---- linux-2.6.18.8/net/ipv4/tcp_input.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/net/ipv4/tcp_input.c 2008-02-15 16:22:16.000000000 -0800
+diff -rpuN linux-2.6.18.8/net/ipv4/tcp_input.c linux-2.6.18-xen-3.3.0/net/ipv4/tcp_input.c
+--- linux-2.6.18.8/net/ipv4/tcp_input.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/ipv4/tcp_input.c 2008-08-21 11:36:07.000000000 +0200
@@ -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.
@@ -139819,9 +210208,9 @@ diff -rpuN linux-2.6.18.8/net/ipv4/tcp_input.c linux-2.6.18-xen-3.2.0/net/ipv4/t
if (len >= icsk->icsk_ack.rcv_mss) {
icsk->icsk_ack.rcv_mss = len;
} else {
-diff -rpuN linux-2.6.18.8/net/ipv4/xfrm4_output.c linux-2.6.18-xen-3.2.0/net/ipv4/xfrm4_output.c
---- linux-2.6.18.8/net/ipv4/xfrm4_output.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/net/ipv4/xfrm4_output.c 2008-02-15 16:22:16.000000000 -0800
+diff -rpuN linux-2.6.18.8/net/ipv4/xfrm4_output.c linux-2.6.18-xen-3.3.0/net/ipv4/xfrm4_output.c
+--- linux-2.6.18.8/net/ipv4/xfrm4_output.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/net/ipv4/xfrm4_output.c 2008-08-21 11:36:07.000000000 +0200
@@ -18,6 +18,8 @@
#include <net/xfrm.h>
#include <net/icmp.h>
@@ -139842,9 +210231,9 @@ diff -rpuN linux-2.6.18.8/net/ipv4/xfrm4_output.c linux-2.6.18-xen-3.2.0/net/ipv
if (skb->ip_summed == CHECKSUM_HW) {
err = skb_checksum_help(skb, 0);
if (err)
-diff -rpuN linux-2.6.18.8/scripts/Makefile.build linux-2.6.18-xen-3.2.0/scripts/Makefile.build
---- linux-2.6.18.8/scripts/Makefile.build 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/scripts/Makefile.build 2008-02-15 16:22:17.000000000 -0800
+diff -rpuN linux-2.6.18.8/scripts/Makefile.build linux-2.6.18-xen-3.3.0/scripts/Makefile.build
+--- linux-2.6.18.8/scripts/Makefile.build 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/scripts/Makefile.build 2008-08-21 11:36:07.000000000 +0200
@@ -68,6 +68,20 @@ ifndef obj
$(warning kbuild: Makefile.build is included improperly)
endif
@@ -139866,9 +210255,9 @@ diff -rpuN linux-2.6.18.8/scripts/Makefile.build linux-2.6.18-xen-3.2.0/scripts/
# ===========================================================================
ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
-diff -rpuN linux-2.6.18.8/scripts/Makefile.lib linux-2.6.18-xen-3.2.0/scripts/Makefile.lib
---- linux-2.6.18.8/scripts/Makefile.lib 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/scripts/Makefile.lib 2008-02-15 16:22:17.000000000 -0800
+diff -rpuN linux-2.6.18.8/scripts/Makefile.lib linux-2.6.18-xen-3.3.0/scripts/Makefile.lib
+--- linux-2.6.18.8/scripts/Makefile.lib 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/scripts/Makefile.lib 2008-08-21 11:36:07.000000000 +0200
@@ -13,6 +13,12 @@ obj-m := $(filter-out $(obj-y),$(obj-m))
lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
@@ -139882,9 +210271,9 @@ diff -rpuN linux-2.6.18.8/scripts/Makefile.lib linux-2.6.18-xen-3.2.0/scripts/Ma
# Handle objects in subdirs
# ---------------------------------------------------------------------------
-diff -rpuN linux-2.6.18.8/scripts/Makefile.xen.awk linux-2.6.18-xen-3.2.0/scripts/Makefile.xen.awk
---- linux-2.6.18.8/scripts/Makefile.xen.awk 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/scripts/Makefile.xen.awk 2008-02-15 16:22:17.000000000 -0800
+diff -rpuN linux-2.6.18.8/scripts/Makefile.xen.awk linux-2.6.18-xen-3.3.0/scripts/Makefile.xen.awk
+--- linux-2.6.18.8/scripts/Makefile.xen.awk 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/scripts/Makefile.xen.awk 2008-08-21 11:36:07.000000000 +0200
@@ -0,0 +1,34 @@
+BEGIN {
+ is_rule = 0
@@ -139920,23 +210309,37 @@ diff -rpuN linux-2.6.18.8/scripts/Makefile.xen.awk linux-2.6.18-xen-3.2.0/script
+ print $0
+ next
+}
-diff -rpuN linux-2.6.18.8/sound/pci/hda/hda_intel.c linux-2.6.18-xen-3.2.0/sound/pci/hda/hda_intel.c
---- linux-2.6.18.8/sound/pci/hda/hda_intel.c 2007-02-23 15:52:30.000000000 -0800
-+++ linux-2.6.18-xen-3.2.0/sound/pci/hda/hda_intel.c 2008-02-15 16:22:18.000000000 -0800
-@@ -80,6 +80,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},
+diff -rpuN linux-2.6.18.8/scripts/mod/sumversion.c linux-2.6.18-xen-3.3.0/scripts/mod/sumversion.c
+--- linux-2.6.18.8/scripts/mod/sumversion.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/scripts/mod/sumversion.c 2008-08-21 11:36:07.000000000 +0200
+@@ -7,6 +7,7 @@
+ #include <ctype.h>
+ #include <errno.h>
+ #include <string.h>
++#include <limits.h>
+ #include "modpost.h"
+
+ /*
+diff -rpuN linux-2.6.18.8/sound/pci/hda/hda_intel.c linux-2.6.18-xen-3.3.0/sound/pci/hda/hda_intel.c
+--- linux-2.6.18.8/sound/pci/hda/hda_intel.c 2007-02-24 00:52:30.000000000 +0100
++++ linux-2.6.18-xen-3.3.0/sound/pci/hda/hda_intel.c 2008-08-21 11:36:07.000000000 +0200
+@@ -80,6 +80,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},
"{Intel, ICH7},"
"{Intel, ESB2},"
"{Intel, ICH8},"
+ "{Intel, ICH9},"
++ "{Intel, ICH10},"
"{ATI, SB450},"
"{ATI, SB600},"
"{ATI, RS600},"
-@@ -1634,6 +1635,8 @@ static struct pci_device_id azx_ids[] =
+@@ -1634,6 +1636,10 @@ static struct pci_device_id azx_ids[] =
{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
+ { 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
+ { 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
++ { 0x8086, 0x3a3e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
++ { 0x8086, 0x3a6e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
{ 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
diff --git a/trunk/2.6.18/30073_nfs-write-corruption.patch b/trunk/2.6.18/30073_nfs-write-corruption.patch
new file mode 100644
index 0000000..a657673
--- /dev/null
+++ b/trunk/2.6.18/30073_nfs-write-corruption.patch
@@ -0,0 +1,76 @@
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Thu, 7 Feb 2008 22:24:07 +0000 (-0500)
+Subject: NFS: Fix a potential file corruption issue when writing
+X-Git-Tag: v2.6.25-rc1~286^2~1
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=5d47a35600270e7115061cb1320ee60ae9bcb6b8
+
+NFS: Fix a potential file corruption issue when writing
+
+If the inode is flagged as having an invalid mapping, then we can't rely on
+the PageUptodate() flag. Ensure that we don't use the "anti-fragmentation"
+write optimisation in nfs_updatepage(), since that will cause NFS to write
+out areas of the page that are no longer guaranteed to be up to date.
+
+A potential corruption could occur in the following scenario:
+
+client 1 client 2
+=============== ===============
+ fd=open("f",O_CREAT|O_WRONLY,0644);
+ write(fd,"fubar\n",6); // cache last page
+ close(fd);
+fd=open("f",O_WRONLY|O_APPEND);
+write(fd,"foo\n",4);
+close(fd);
+
+ fd=open("f",O_WRONLY|O_APPEND);
+ write(fd,"bar\n",4);
+ close(fd);
+-----
+The bug may lead to the file "f" reading 'fubar\n\0\0\0\nbar\n' because
+client 2 does not update the cached page after re-opening the file for
+write. Instead it keeps it marked as PageUptodate() until someone calls
+invaldate_inode_pages2() (typically by calling read()).
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+---
+
+Backported to Debian's 2.6.18 by dann frazier <danfn@debian.org>
+
+diff -urpN linux-source-2.6.18.orig/fs/nfs/write.c linux-source-2.6.18/fs/nfs/write.c
+--- linux-source-2.6.18.orig/fs/nfs/write.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/fs/nfs/write.c 2008-03-13 01:16:30.000000000 -0600
+@@ -805,6 +805,17 @@ int nfs_flush_incompatible(struct file *
+ }
+
+ /*
++ * If the page cache is marked as unsafe or invalid, then we can't rely on
++ * the PageUptodate() flag. In this case, we will need to turn off
++ * write optimisations that depend on the page contents being correct.
++ */
++static int nfs_write_pageuptodate(struct page *page, struct inode *inode)
++{
++ return PageUptodate(page) &&
++ !(NFS_I(inode)->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA));
++}
++
++/*
+ * Update and possibly write a cached page of an NFS file.
+ *
+ * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad
+@@ -836,10 +847,13 @@ int nfs_updatepage(struct file *file, st
+ }
+
+ /* If we're not using byte range locks, and we know the page
+- * is entirely in cache, it may be more efficient to avoid
+- * fragmenting write requests.
++ * is up to date, it may be more efficient to extend the write
++ * to cover the entire page in order to avoid fragmentation
++ * inefficiencies.
+ */
+- if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
++ if (nfs_write_pageuptodate(page, inode) &&
++ inode->i_flock == NULL &&
++ !(file->f_flags & O_SYNC)) {
+ loff_t end_offs = i_size_read(inode) - 1;
+ unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT;
+
diff --git a/trunk/2.6.18/30074_x86-clear-df-before-calling-signal-handler.patch b/trunk/2.6.18/30074_x86-clear-df-before-calling-signal-handler.patch
new file mode 100644
index 0000000..76481fb
--- /dev/null
+++ b/trunk/2.6.18/30074_x86-clear-df-before-calling-signal-handler.patch
@@ -0,0 +1,57 @@
+Index: linux-2.6.18.8/arch/i386/kernel/signal.c
+===================================================================
+--- linux-2.6.18.8.orig/arch/i386/kernel/signal.c
++++ linux-2.6.18.8/arch/i386/kernel/signal.c
+@@ -391,7 +391,7 @@ static int setup_frame(int sig, struct k
+ * The tracer may want to single-step inside the
+ * handler too.
+ */
+- regs->eflags &= ~TF_MASK;
++ regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+@@ -485,7 +485,7 @@ static int setup_rt_frame(int sig, struc
+ * The tracer may want to single-step inside the
+ * handler too.
+ */
+- regs->eflags &= ~TF_MASK;
++ regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+Index: linux-2.6.18.8/arch/x86_64/ia32/ia32_signal.c
+===================================================================
+--- linux-2.6.18.8.orig/arch/x86_64/ia32/ia32_signal.c
++++ linux-2.6.18.8/arch/x86_64/ia32/ia32_signal.c
+@@ -493,7 +493,7 @@ int ia32_setup_frame(int sig, struct k_s
+ regs->ss = __USER32_DS;
+
+ set_fs(USER_DS);
+- regs->eflags &= ~TF_MASK;
++ regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+@@ -589,7 +589,7 @@ int ia32_setup_rt_frame(int sig, struct
+ regs->ss = __USER32_DS;
+
+ set_fs(USER_DS);
+- regs->eflags &= ~TF_MASK;
++ regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+Index: linux-2.6.18.8/arch/x86_64/kernel/signal.c
+===================================================================
+--- linux-2.6.18.8.orig/arch/x86_64/kernel/signal.c
++++ linux-2.6.18.8/arch/x86_64/kernel/signal.c
+@@ -302,7 +302,7 @@ static int setup_rt_frame(int sig, struc
+ see include/asm-x86_64/uaccess.h for details. */
+ set_fs(USER_DS);
+
+- regs->eflags &= ~TF_MASK;
++ regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+ #ifdef DEBUG_SIG
diff --git a/trunk/2.6.18/30075_3w-xxxx-bigmem-corruption.patch b/trunk/2.6.18/30075_3w-xxxx-bigmem-corruption.patch
new file mode 100644
index 0000000..400fcdf
--- /dev/null
+++ b/trunk/2.6.18/30075_3w-xxxx-bigmem-corruption.patch
@@ -0,0 +1,42 @@
+Changes extracted from:
+ http://www.3ware.com/KB/attachments/183-3w-xxxx-2.6.18-GUIDa2c1e9da5ebd4284a41f7be6cee86ff1.tgz
+Described at:
+ http://www.3ware.com/KB/article.aspx?id=15243
+
+Recent upstream kernels have been converted to the new
+sg list accessor API, so this fix isn't applicable there.
+
+diff -urpN linux-source-2.6.18.orig/drivers/scsi/3w-xxxx.c linux-source-2.6.18/drivers/scsi/3w-xxxx.c
+--- linux-source-2.6.18.orig/drivers/scsi/3w-xxxx.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/drivers/scsi/3w-xxxx.c 2008-04-21 21:34:10.000000000 -0600
+@@ -1286,7 +1286,7 @@ static int tw_map_scsi_sg_data(struct pc
+ if (cmd->use_sg == 0)
+ return 0;
+
+- use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
++ use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction);
+
+ if (use_sg == 0) {
+ printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
+@@ -1308,7 +1308,7 @@ static u32 tw_map_scsi_single_data(struc
+ if (cmd->request_bufflen == 0)
+ return 0;
+
+- mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL);
++ mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, cmd->sc_data_direction);
+
+ if (mapping == 0) {
+ printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
+@@ -1327,10 +1327,10 @@ static void tw_unmap_scsi_data(struct pc
+
+ switch(cmd->SCp.phase) {
+ case TW_PHASE_SINGLE:
+- pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
++ pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, cmd->sc_data_direction);
+ break;
+ case TW_PHASE_SGLIST:
+- pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
++ pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction);
+ break;
+ }
+ } /* End tw_unmap_scsi_data() */
diff --git a/trunk/2.6.18/30076_dnotify-race-locking.patch b/trunk/2.6.18/30076_dnotify-race-locking.patch
new file mode 100644
index 0000000..a186b18
--- /dev/null
+++ b/trunk/2.6.18/30076_dnotify-race-locking.patch
@@ -0,0 +1,29 @@
+Index: linux-2.6.18.8/fs/dnotify.c
+===================================================================
+--- linux-2.6.18.8.orig/fs/dnotify.c
++++ linux-2.6.18.8/fs/dnotify.c
+@@ -67,6 +67,9 @@ int fcntl_dirnotify(int fd, struct file
+ struct dnotify_struct **prev;
+ struct inode *inode;
+ fl_owner_t id = current->files;
++#ifndef __GENKSYMS__
++ struct file *f;
++#endif
+ int error = 0;
+
+ if ((arg & ~DN_MULTISHOT) == 0) {
+@@ -93,8 +96,13 @@ int fcntl_dirnotify(int fd, struct file
+ prev = &odn->dn_next;
+ }
+
++ rcu_read_lock();
++ f = fcheck(fd);
++ rcu_read_unlock();
+ /* we'd lost the race with close(), sod off silently */
+- if (fcheck(fd) != filp)
++ /* note that inode->i_lock prevents reordering problems
++ * between accesses to descriptor table and ->i_dnotify */
++ if (f != filp)
+ goto out_free;
+
+ error = f_setown(filp, current->pid, 0);
diff --git a/trunk/2.6.18/30077_sctp-make-sure-n-sizeof-does-not-overflow.patch b/trunk/2.6.18/30077_sctp-make-sure-n-sizeof-does-not-overflow.patch
new file mode 100644
index 0000000..a36c02d
--- /dev/null
+++ b/trunk/2.6.18/30077_sctp-make-sure-n-sizeof-does-not-overflow.patch
@@ -0,0 +1,29 @@
+commit 735ce972fbc8a65fb17788debd7bbe7b4383cc62
+Author: David S. Miller <davem@davemloft.net>
+Date: Fri Jun 20 22:04:34 2008 -0700
+
+ sctp: Make sure N * sizeof(union sctp_addr) does not overflow.
+
+ As noticed by Gabriel Campana, the kmalloc() length arg
+ passed in by sctp_getsockopt_local_addrs_old() can overflow
+ if ->addr_num is large enough.
+
+ Therefore, enforce an appropriate limit.
+
+ Signed-off-by: David S. Miller <davem@davemloft.net>
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index e7e3baf..0dbcde6 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -4401,7 +4401,9 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
+ if (copy_from_user(&getaddrs, optval, len))
+ return -EFAULT;
+
+- if (getaddrs.addr_num <= 0) return -EINVAL;
++ if (getaddrs.addr_num <= 0 ||
++ getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr)))
++ return -EINVAL;
+ /*
+ * For UDP-style sockets, id specifies the association to query.
+ * If the id field is set to the value '0' then the locally bound
diff --git a/trunk/2.6.18/30078_esp-iv-in-linear-part-of-skb.patch b/trunk/2.6.18/30078_esp-iv-in-linear-part-of-skb.patch
new file mode 100644
index 0000000..59fb682
--- /dev/null
+++ b/trunk/2.6.18/30078_esp-iv-in-linear-part-of-skb.patch
@@ -0,0 +1,48 @@
+From: Thomas Graf <tgraf@suug.ch>
+Date: Thu, 27 Mar 2008 23:08:03 +0000 (-0700)
+Subject: (CVE-2007-6282) [ESP]: Ensure IV is in linear part of the skb to avoid BUG() due ...
+X-Git-Url: http://kernel.ubuntu.com/git?p=ubuntu-security%2Fubuntu-dapper.git;a=commitdiff_plain;h=3f83e11fbd494f5e40db1a7bbd2b780118b712a1
+
+(CVE-2007-6282) [ESP]: Ensure IV is in linear part of the skb to avoid BUG() due to OOB access
+
+[linux-2.6: 920fc941a9617f95ccb283037fe6f8a38d95bb69]
+
+ESP does not account for the IV size when calling pskb_may_pull() to
+ensure everything it accesses directly is within the linear part of a
+potential fragment. This results in a BUG() being triggered when the
+both the IPv4 and IPv6 ESP stack is fed with an skb where the first
+fragment ends between the end of the esp header and the end of the IV.
+
+This bug was found by Dirk Nehring <dnehring@gmx.net> .
+
+Signed-off-by: Thomas Graf <tgraf@suug.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Kees Cook <kees.cook@canonical.com>
+---
+
+Adjusted to apply to Debian's 2.6.18 by dann frazier <dannf@debian.org>
+
+diff -urpN linux-source-2.6.18.orig/net/ipv4/esp4.c linux-source-2.6.18/net/ipv4/esp4.c
+--- linux-source-2.6.18.orig/net/ipv4/esp4.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/net/ipv4/esp4.c 2008-06-24 22:47:45.000000000 -0600
+@@ -147,7 +147,7 @@ static int esp_input(struct xfrm_state *
+ struct scatterlist *sg;
+ int padlen;
+
+- if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
++ if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen))
+ goto out;
+
+ if (elen <= 0 || (elen & (blksize-1)))
+diff -urpN linux-source-2.6.18.orig/net/ipv6/esp6.c linux-source-2.6.18/net/ipv6/esp6.c
+--- linux-source-2.6.18.orig/net/ipv6/esp6.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/net/ipv6/esp6.c 2008-06-24 22:47:45.000000000 -0600
+@@ -143,7 +143,7 @@ static int esp6_input(struct xfrm_state
+ int nfrags;
+ int ret = 0;
+
+- if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) {
++ if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen)) {
+ ret = -EINVAL;
+ goto out;
+ }
diff --git a/trunk/2.6.18/30079a_amd64-fix-zeroing-on-exception-in-copy_user-pre.patch b/trunk/2.6.18/30079a_amd64-fix-zeroing-on-exception-in-copy_user-pre.patch
new file mode 100644
index 0000000..17e1346
--- /dev/null
+++ b/trunk/2.6.18/30079a_amd64-fix-zeroing-on-exception-in-copy_user-pre.patch
@@ -0,0 +1,798 @@
+commit 8d379dad8f1670d233ac67b76b1c5a42ad3714a3
+Author: Jan Beulich <jbeulich@novell.com>
+Date: Tue Sep 26 10:52:32 2006 +0200
+
+ [PATCH] annotate arch/x86_64/lib/*.S
+
+ Add unwind annotations to arch/x86_64/lib/*.S, and also use the macros
+ provided by linux/linkage.h where-ever possible.
+
+ Some of the alternative instructions handling needed to be adjusted so
+ that the replacement code would also have valid unwind information.
+
+ Signed-off-by: Jan Beulich <jbeulich@novell.com>
+ Signed-off-by: Andi Kleen <ak@suse.de>
+
+diff --git a/arch/x86_64/lib/clear_page.S b/arch/x86_64/lib/clear_page.S
+index 1f81b79..9a10a78 100644
+--- a/arch/x86_64/lib/clear_page.S
++++ b/arch/x86_64/lib/clear_page.S
+@@ -1,10 +1,22 @@
++#include <linux/linkage.h>
++#include <asm/dwarf2.h>
++
+ /*
+ * Zero a page.
+ * rdi page
+ */
+- .globl clear_page
+- .p2align 4
+-clear_page:
++ ALIGN
++clear_page_c:
++ CFI_STARTPROC
++ movl $4096/8,%ecx
++ xorl %eax,%eax
++ rep stosq
++ ret
++ CFI_ENDPROC
++ENDPROC(clear_page)
++
++ENTRY(clear_page)
++ CFI_STARTPROC
+ xorl %eax,%eax
+ movl $4096/64,%ecx
+ .p2align 4
+@@ -23,28 +35,25 @@ clear_page:
+ jnz .Lloop
+ nop
+ ret
+-clear_page_end:
++ CFI_ENDPROC
++.Lclear_page_end:
++ENDPROC(clear_page)
+
+ /* Some CPUs run faster using the string instructions.
+ It is also a lot simpler. Use this when possible */
+
+ #include <asm/cpufeature.h>
+
++ .section .altinstr_replacement,"ax"
++1: .byte 0xeb /* jmp <disp8> */
++ .byte (clear_page_c - clear_page) - (2f - 1b) /* offset */
++2:
++ .previous
+ .section .altinstructions,"a"
+ .align 8
+- .quad clear_page
+- .quad clear_page_c
+- .byte X86_FEATURE_REP_GOOD
+- .byte clear_page_end-clear_page
+- .byte clear_page_c_end-clear_page_c
+- .previous
+-
+- .section .altinstr_replacement,"ax"
+-clear_page_c:
+- movl $4096/8,%ecx
+- xorl %eax,%eax
+- rep
+- stosq
+- ret
+-clear_page_c_end:
++ .quad clear_page
++ .quad 1b
++ .byte X86_FEATURE_REP_GOOD
++ .byte .Lclear_page_end - clear_page
++ .byte 2b - 1b
+ .previous
+diff --git a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S
+index 8fa19d9..0ebb03b 100644
+--- a/arch/x86_64/lib/copy_page.S
++++ b/arch/x86_64/lib/copy_page.S
+@@ -1,17 +1,33 @@
+ /* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */
+
++#include <linux/config.h>
++#include <linux/linkage.h>
++#include <asm/dwarf2.h>
++
++ ALIGN
++copy_page_c:
++ CFI_STARTPROC
++ movl $4096/8,%ecx
++ rep movsq
++ ret
++ CFI_ENDPROC
++ENDPROC(copy_page_c)
++
+ /* Don't use streaming store because it's better when the target
+ ends up in cache. */
+
+ /* Could vary the prefetch distance based on SMP/UP */
+
+- .globl copy_page
+- .p2align 4
+-copy_page:
++ENTRY(copy_page)
++ CFI_STARTPROC
+ subq $3*8,%rsp
++ CFI_ADJUST_CFA_OFFSET 3*8
+ movq %rbx,(%rsp)
++ CFI_REL_OFFSET rbx, 0
+ movq %r12,1*8(%rsp)
++ CFI_REL_OFFSET r12, 1*8
+ movq %r13,2*8(%rsp)
++ CFI_REL_OFFSET r13, 2*8
+
+ movl $(4096/64)-5,%ecx
+ .p2align 4
+@@ -72,30 +88,33 @@ copy_page:
+ jnz .Loop2
+
+ movq (%rsp),%rbx
++ CFI_RESTORE rbx
+ movq 1*8(%rsp),%r12
++ CFI_RESTORE r12
+ movq 2*8(%rsp),%r13
++ CFI_RESTORE r13
+ addq $3*8,%rsp
++ CFI_ADJUST_CFA_OFFSET -3*8
+ ret
++.Lcopy_page_end:
++ CFI_ENDPROC
++ENDPROC(copy_page)
+
+ /* Some CPUs run faster using the string copy instructions.
+ It is also a lot simpler. Use this when possible */
+
+ #include <asm/cpufeature.h>
+
++ .section .altinstr_replacement,"ax"
++1: .byte 0xeb /* jmp <disp8> */
++ .byte (copy_page_c - copy_page) - (2f - 1b) /* offset */
++2:
++ .previous
+ .section .altinstructions,"a"
+ .align 8
+- .quad copy_page
+- .quad copy_page_c
+- .byte X86_FEATURE_REP_GOOD
+- .byte copy_page_c_end-copy_page_c
+- .byte copy_page_c_end-copy_page_c
+- .previous
+-
+- .section .altinstr_replacement,"ax"
+-copy_page_c:
+- movl $4096/8,%ecx
+- rep
+- movsq
+- ret
+-copy_page_c_end:
++ .quad copy_page
++ .quad 1b
++ .byte X86_FEATURE_REP_GOOD
++ .byte .Lcopy_page_end - copy_page
++ .byte 2b - 1b
+ .previous
+diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S
+index f64569b..962f3a6 100644
+--- a/arch/x86_64/lib/copy_user.S
++++ b/arch/x86_64/lib/copy_user.S
+@@ -4,6 +4,9 @@
+ * Functions to copy from and to user space.
+ */
+
++#include <linux/linkage.h>
++#include <asm/dwarf2.h>
++
+ #define FIX_ALIGNMENT 1
+
+ #include <asm/current.h>
+@@ -12,9 +15,8 @@
+ #include <asm/cpufeature.h>
+
+ /* Standard copy_to_user with segment limit checking */
+- .globl copy_to_user
+- .p2align 4
+-copy_to_user:
++ENTRY(copy_to_user)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%rax)
+ movq %rdi,%rcx
+ addq %rdx,%rcx
+@@ -25,9 +27,11 @@ copy_to_user:
+ .byte 0xe9 /* 32bit jump */
+ .long .Lcug-1f
+ 1:
++ CFI_ENDPROC
++ENDPROC(copy_to_user)
+
+ .section .altinstr_replacement,"ax"
+-3: .byte 0xe9 /* replacement jmp with 8 bit immediate */
++3: .byte 0xe9 /* replacement jmp with 32 bit immediate */
+ .long copy_user_generic_c-1b /* offset */
+ .previous
+ .section .altinstructions,"a"
+@@ -40,9 +44,8 @@ copy_to_user:
+ .previous
+
+ /* Standard copy_from_user with segment limit checking */
+- .globl copy_from_user
+- .p2align 4
+-copy_from_user:
++ENTRY(copy_from_user)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%rax)
+ movq %rsi,%rcx
+ addq %rdx,%rcx
+@@ -50,10 +53,13 @@ copy_from_user:
+ cmpq threadinfo_addr_limit(%rax),%rcx
+ jae bad_from_user
+ /* FALL THROUGH to copy_user_generic */
++ CFI_ENDPROC
++ENDPROC(copy_from_user)
+
+ .section .fixup,"ax"
+ /* must zero dest */
+ bad_from_user:
++ CFI_STARTPROC
+ movl %edx,%ecx
+ xorl %eax,%eax
+ rep
+@@ -61,6 +67,8 @@ bad_from_user:
+ bad_to_user:
+ movl %edx,%eax
+ ret
++ CFI_ENDPROC
++END(bad_from_user)
+ .previous
+
+
+@@ -75,9 +83,8 @@ bad_to_user:
+ * Output:
+ * eax uncopied bytes or 0 if successful.
+ */
+- .globl copy_user_generic
+- .p2align 4
+-copy_user_generic:
++ENTRY(copy_user_generic)
++ CFI_STARTPROC
+ .byte 0x66,0x66,0x90 /* 5 byte nop for replacement jump */
+ .byte 0x66,0x90
+ 1:
+@@ -95,6 +102,8 @@ copy_user_generic:
+ .previous
+ .Lcug:
+ pushq %rbx
++ CFI_ADJUST_CFA_OFFSET 8
++ CFI_REL_OFFSET rbx, 0
+ xorl %eax,%eax /*zero for the exception handler */
+
+ #ifdef FIX_ALIGNMENT
+@@ -168,9 +177,13 @@ copy_user_generic:
+ decl %ecx
+ jnz .Lloop_1
+
++ CFI_REMEMBER_STATE
+ .Lende:
+ popq %rbx
++ CFI_ADJUST_CFA_OFFSET -8
++ CFI_RESTORE rbx
+ ret
++ CFI_RESTORE_STATE
+
+ #ifdef FIX_ALIGNMENT
+ /* align destination */
+@@ -261,6 +274,9 @@ copy_user_generic:
+ .Le_zero:
+ movq %rdx,%rax
+ jmp .Lende
++ CFI_ENDPROC
++ENDPROC(copy_user_generic)
++
+
+ /* Some CPUs run faster using the string copy instructions.
+ This is also a lot simpler. Use them when possible.
+@@ -282,6 +298,7 @@ copy_user_generic:
+ * this please consider this.
+ */
+ copy_user_generic_c:
++ CFI_STARTPROC
+ movl %edx,%ecx
+ shrl $3,%ecx
+ andl $7,%edx
+@@ -294,6 +311,8 @@ copy_user_generic_c:
+ ret
+ 3: lea (%rdx,%rcx,8),%rax
+ ret
++ CFI_ENDPROC
++END(copy_user_generic_c)
+
+ .section __ex_table,"a"
+ .quad 1b,3b
+diff --git a/arch/x86_64/lib/csum-copy.S b/arch/x86_64/lib/csum-copy.S
+index 72fd55e..f0dba36 100644
+--- a/arch/x86_64/lib/csum-copy.S
++++ b/arch/x86_64/lib/csum-copy.S
+@@ -5,8 +5,9 @@
+ * License. See the file COPYING in the main directory of this archive
+ * for more details. No warranty for anything given at all.
+ */
+- #include <linux/linkage.h>
+- #include <asm/errno.h>
++#include <linux/linkage.h>
++#include <asm/dwarf2.h>
++#include <asm/errno.h>
+
+ /*
+ * Checksum copy with exception handling.
+@@ -53,19 +54,24 @@
+ .endm
+
+
+- .globl csum_partial_copy_generic
+- .p2align 4
+-csum_partial_copy_generic:
++ENTRY(csum_partial_copy_generic)
++ CFI_STARTPROC
+ cmpl $3*64,%edx
+ jle .Lignore
+
+ .Lignore:
+ subq $7*8,%rsp
++ CFI_ADJUST_CFA_OFFSET 7*8
+ movq %rbx,2*8(%rsp)
++ CFI_REL_OFFSET rbx, 2*8
+ movq %r12,3*8(%rsp)
++ CFI_REL_OFFSET r12, 3*8
+ movq %r14,4*8(%rsp)
++ CFI_REL_OFFSET r14, 4*8
+ movq %r13,5*8(%rsp)
++ CFI_REL_OFFSET r13, 5*8
+ movq %rbp,6*8(%rsp)
++ CFI_REL_OFFSET rbp, 6*8
+
+ movq %r8,(%rsp)
+ movq %r9,1*8(%rsp)
+@@ -208,14 +214,22 @@ csum_partial_copy_generic:
+ addl %ebx,%eax
+ adcl %r9d,%eax /* carry */
+
++ CFI_REMEMBER_STATE
+ .Lende:
+ movq 2*8(%rsp),%rbx
++ CFI_RESTORE rbx
+ movq 3*8(%rsp),%r12
++ CFI_RESTORE r12
+ movq 4*8(%rsp),%r14
++ CFI_RESTORE r14
+ movq 5*8(%rsp),%r13
++ CFI_RESTORE r13
+ movq 6*8(%rsp),%rbp
++ CFI_RESTORE rbp
+ addq $7*8,%rsp
++ CFI_ADJUST_CFA_OFFSET -7*8
+ ret
++ CFI_RESTORE_STATE
+
+ /* Exception handlers. Very simple, zeroing is done in the wrappers */
+ .Lbad_source:
+@@ -231,3 +245,5 @@ csum_partial_copy_generic:
+ jz .Lende
+ movl $-EFAULT,(%rax)
+ jmp .Lende
++ CFI_ENDPROC
++ENDPROC(csum_partial_copy_generic)
+diff --git a/arch/x86_64/lib/getuser.S b/arch/x86_64/lib/getuser.S
+index 3844d5e..5448876 100644
+--- a/arch/x86_64/lib/getuser.S
++++ b/arch/x86_64/lib/getuser.S
+@@ -27,25 +27,26 @@
+ */
+
+ #include <linux/linkage.h>
++#include <asm/dwarf2.h>
+ #include <asm/page.h>
+ #include <asm/errno.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/thread_info.h>
+
+ .text
+- .p2align 4
+-.globl __get_user_1
+-__get_user_1:
++ENTRY(__get_user_1)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%r8)
+ cmpq threadinfo_addr_limit(%r8),%rcx
+ jae bad_get_user
+ 1: movzb (%rcx),%edx
+ xorl %eax,%eax
+ ret
++ CFI_ENDPROC
++ENDPROC(__get_user_1)
+
+- .p2align 4
+-.globl __get_user_2
+-__get_user_2:
++ENTRY(__get_user_2)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%r8)
+ addq $1,%rcx
+ jc 20f
+@@ -57,10 +58,11 @@ __get_user_2:
+ ret
+ 20: decq %rcx
+ jmp bad_get_user
++ CFI_ENDPROC
++ENDPROC(__get_user_2)
+
+- .p2align 4
+-.globl __get_user_4
+-__get_user_4:
++ENTRY(__get_user_4)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%r8)
+ addq $3,%rcx
+ jc 30f
+@@ -72,10 +74,11 @@ __get_user_4:
+ ret
+ 30: subq $3,%rcx
+ jmp bad_get_user
++ CFI_ENDPROC
++ENDPROC(__get_user_4)
+
+- .p2align 4
+-.globl __get_user_8
+-__get_user_8:
++ENTRY(__get_user_8)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%r8)
+ addq $7,%rcx
+ jc 40f
+@@ -87,11 +90,16 @@ __get_user_8:
+ ret
+ 40: subq $7,%rcx
+ jmp bad_get_user
++ CFI_ENDPROC
++ENDPROC(__get_user_8)
+
+ bad_get_user:
++ CFI_STARTPROC
+ xorl %edx,%edx
+ movq $(-EFAULT),%rax
+ ret
++ CFI_ENDPROC
++END(bad_get_user)
+
+ .section __ex_table,"a"
+ .quad 1b,bad_get_user
+diff --git a/arch/x86_64/lib/iomap_copy.S b/arch/x86_64/lib/iomap_copy.S
+index 8bbade5..05a95e7 100644
+--- a/arch/x86_64/lib/iomap_copy.S
++++ b/arch/x86_64/lib/iomap_copy.S
+@@ -15,12 +15,16 @@
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
++#include <linux/linkage.h>
++#include <asm/dwarf2.h>
++
+ /*
+ * override generic version in lib/iomap_copy.c
+ */
+- .globl __iowrite32_copy
+- .p2align 4
+-__iowrite32_copy:
++ENTRY(__iowrite32_copy)
++ CFI_STARTPROC
+ movl %edx,%ecx
+ rep movsd
+ ret
++ CFI_ENDPROC
++ENDPROC(__iowrite32_copy)
+diff --git a/arch/x86_64/lib/memcpy.S b/arch/x86_64/lib/memcpy.S
+index 5554948..967b22f 100644
+--- a/arch/x86_64/lib/memcpy.S
++++ b/arch/x86_64/lib/memcpy.S
+@@ -1,6 +1,10 @@
+ /* Copyright 2002 Andi Kleen */
+
+- #include <asm/cpufeature.h>
++#include <linux/config.h>
++#include <linux/linkage.h>
++#include <asm/dwarf2.h>
++#include <asm/cpufeature.h>
++
+ /*
+ * memcpy - Copy a memory block.
+ *
+@@ -13,12 +17,26 @@
+ * rax original destination
+ */
+
+- .globl __memcpy
+- .globl memcpy
+- .p2align 4
+-__memcpy:
+-memcpy:
++ ALIGN
++memcpy_c:
++ CFI_STARTPROC
++ movq %rdi,%rax
++ movl %edx,%ecx
++ shrl $3,%ecx
++ andl $7,%edx
++ rep movsq
++ movl %edx,%ecx
++ rep movsb
++ ret
++ CFI_ENDPROC
++ENDPROC(memcpy_c)
++
++ENTRY(__memcpy)
++ENTRY(memcpy)
++ CFI_STARTPROC
+ pushq %rbx
++ CFI_ADJUST_CFA_OFFSET 8
++ CFI_REL_OFFSET rbx, 0
+ movq %rdi,%rax
+
+ movl %edx,%ecx
+@@ -86,36 +104,27 @@ memcpy:
+
+ .Lende:
+ popq %rbx
++ CFI_ADJUST_CFA_OFFSET -8
++ CFI_RESTORE rbx
+ ret
+ .Lfinal:
++ CFI_ENDPROC
++ENDPROC(memcpy)
++ENDPROC(__memcpy)
+
+ /* Some CPUs run faster using the string copy instructions.
+ It is also a lot simpler. Use this when possible */
+
++ .section .altinstr_replacement,"ax"
++1: .byte 0xeb /* jmp <disp8> */
++ .byte (memcpy_c - memcpy) - (2f - 1b) /* offset */
++2:
++ .previous
+ .section .altinstructions,"a"
+ .align 8
+- .quad memcpy
+- .quad memcpy_c
+- .byte X86_FEATURE_REP_GOOD
+- .byte .Lfinal-memcpy
+- .byte memcpy_c_end-memcpy_c
+- .previous
+-
+- .section .altinstr_replacement,"ax"
+- /* rdi destination
+- * rsi source
+- * rdx count
+- */
+-memcpy_c:
+- movq %rdi,%rax
+- movl %edx,%ecx
+- shrl $3,%ecx
+- andl $7,%edx
+- rep
+- movsq
+- movl %edx,%ecx
+- rep
+- movsb
+- ret
+-memcpy_c_end:
++ .quad memcpy
++ .quad 1b
++ .byte X86_FEATURE_REP_GOOD
++ .byte .Lfinal - memcpy
++ .byte 2b - 1b
+ .previous
+diff --git a/arch/x86_64/lib/memset.S b/arch/x86_64/lib/memset.S
+index ad397f2..09ed1f6 100644
+--- a/arch/x86_64/lib/memset.S
++++ b/arch/x86_64/lib/memset.S
+@@ -1,4 +1,9 @@
+ /* Copyright 2002 Andi Kleen, SuSE Labs */
++
++#include <linux/config.h>
++#include <linux/linkage.h>
++#include <asm/dwarf2.h>
++
+ /*
+ * ISO C memset - set a memory block to a byte value.
+ *
+@@ -8,11 +13,29 @@
+ *
+ * rax original destination
+ */
+- .globl __memset
+- .globl memset
+- .p2align 4
+-memset:
+-__memset:
++ ALIGN
++memset_c:
++ CFI_STARTPROC
++ movq %rdi,%r9
++ movl %edx,%r8d
++ andl $7,%r8d
++ movl %edx,%ecx
++ shrl $3,%ecx
++ /* expand byte value */
++ movzbl %sil,%esi
++ movabs $0x0101010101010101,%rax
++ mulq %rsi /* with rax, clobbers rdx */
++ rep stosq
++ movl %r8d,%ecx
++ rep stosb
++ movq %r9,%rax
++ ret
++ CFI_ENDPROC
++ENDPROC(memset_c)
++
++ENTRY(memset)
++ENTRY(__memset)
++ CFI_STARTPROC
+ movq %rdi,%r10
+ movq %rdx,%r11
+
+@@ -25,6 +48,7 @@ __memset:
+ movl %edi,%r9d
+ andl $7,%r9d
+ jnz .Lbad_alignment
++ CFI_REMEMBER_STATE
+ .Lafter_bad_alignment:
+
+ movl %r11d,%ecx
+@@ -75,6 +99,7 @@ __memset:
+ movq %r10,%rax
+ ret
+
++ CFI_RESTORE_STATE
+ .Lbad_alignment:
+ cmpq $7,%r11
+ jbe .Lhandle_7
+@@ -84,42 +109,26 @@ __memset:
+ addq %r8,%rdi
+ subq %r8,%r11
+ jmp .Lafter_bad_alignment
++.Lfinal:
++ CFI_ENDPROC
++ENDPROC(memset)
++ENDPROC(__memset)
+
+ /* Some CPUs run faster using the string instructions.
+ It is also a lot simpler. Use this when possible */
+
+ #include <asm/cpufeature.h>
+
++ .section .altinstr_replacement,"ax"
++1: .byte 0xeb /* jmp <disp8> */
++ .byte (memset_c - memset) - (2f - 1b) /* offset */
++2:
++ .previous
+ .section .altinstructions,"a"
+ .align 8
+- .quad memset
+- .quad memset_c
+- .byte X86_FEATURE_REP_GOOD
+- .byte memset_c_end-memset_c
+- .byte memset_c_end-memset_c
+- .previous
+-
+- .section .altinstr_replacement,"ax"
+- /* rdi destination
+- * rsi value
+- * rdx count
+- */
+-memset_c:
+- movq %rdi,%r9
+- movl %edx,%r8d
+- andl $7,%r8d
+- movl %edx,%ecx
+- shrl $3,%ecx
+- /* expand byte value */
+- movzbl %sil,%esi
+- movabs $0x0101010101010101,%rax
+- mulq %rsi /* with rax, clobbers rdx */
+- rep
+- stosq
+- movl %r8d,%ecx
+- rep
+- stosb
+- movq %r9,%rax
+- ret
+-memset_c_end:
++ .quad memset
++ .quad 1b
++ .byte X86_FEATURE_REP_GOOD
++ .byte .Lfinal - memset
++ .byte 2b - 1b
+ .previous
+diff --git a/arch/x86_64/lib/putuser.S b/arch/x86_64/lib/putuser.S
+index 7f55939..4989f5a 100644
+--- a/arch/x86_64/lib/putuser.S
++++ b/arch/x86_64/lib/putuser.S
+@@ -25,25 +25,26 @@
+ */
+
+ #include <linux/linkage.h>
++#include <asm/dwarf2.h>
+ #include <asm/page.h>
+ #include <asm/errno.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/thread_info.h>
+
+ .text
+- .p2align 4
+-.globl __put_user_1
+-__put_user_1:
++ENTRY(__put_user_1)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%r8)
+ cmpq threadinfo_addr_limit(%r8),%rcx
+ jae bad_put_user
+ 1: movb %dl,(%rcx)
+ xorl %eax,%eax
+ ret
++ CFI_ENDPROC
++ENDPROC(__put_user_1)
+
+- .p2align 4
+-.globl __put_user_2
+-__put_user_2:
++ENTRY(__put_user_2)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%r8)
+ addq $1,%rcx
+ jc 20f
+@@ -55,10 +56,11 @@ __put_user_2:
+ ret
+ 20: decq %rcx
+ jmp bad_put_user
++ CFI_ENDPROC
++ENDPROC(__put_user_2)
+
+- .p2align 4
+-.globl __put_user_4
+-__put_user_4:
++ENTRY(__put_user_4)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%r8)
+ addq $3,%rcx
+ jc 30f
+@@ -70,10 +72,11 @@ __put_user_4:
+ ret
+ 30: subq $3,%rcx
+ jmp bad_put_user
++ CFI_ENDPROC
++ENDPROC(__put_user_4)
+
+- .p2align 4
+-.globl __put_user_8
+-__put_user_8:
++ENTRY(__put_user_8)
++ CFI_STARTPROC
+ GET_THREAD_INFO(%r8)
+ addq $7,%rcx
+ jc 40f
+@@ -85,10 +88,15 @@ __put_user_8:
+ ret
+ 40: subq $7,%rcx
+ jmp bad_put_user
++ CFI_ENDPROC
++ENDPROC(__put_user_8)
+
+ bad_put_user:
++ CFI_STARTPROC
+ movq $(-EFAULT),%rax
+ ret
++ CFI_ENDPROC
++END(bad_put_user)
+
+ .section __ex_table,"a"
+ .quad 1b,bad_put_user
diff --git a/trunk/2.6.18/30079b_amd64-fix-zeroing-on-exception-in-copy_user.patch b/trunk/2.6.18/30079b_amd64-fix-zeroing-on-exception-in-copy_user.patch
new file mode 100644
index 0000000..4530d87
--- /dev/null
+++ b/trunk/2.6.18/30079b_amd64-fix-zeroing-on-exception-in-copy_user.patch
@@ -0,0 +1,272 @@
+commit 3022d734a54cbd2b65eea9a024564821101b4a9a
+Author: Andi Kleen <ak@suse.de>
+Date: Tue Sep 26 10:52:39 2006 +0200
+
+ [PATCH] Fix zeroing on exception in copy_*_user
+
+ - Don't zero for __copy_from_user_inatomic following i386.
+ This will prevent spurious zeros for parallel file system writers when
+ one does a exception
+ - The string instruction version didn't zero the output on
+ exception. Oops.
+
+ Also I cleaned up the code a bit while I was at it and added a minor
+ optimization to the string instruction path.
+
+ Signed-off-by: Andi Kleen <ak@suse.de>
+
+diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
+index 370952c..c3454af 100644
+--- a/arch/x86_64/kernel/x8664_ksyms.c
++++ b/arch/x86_64/kernel/x8664_ksyms.c
+@@ -29,6 +29,7 @@ EXPORT_SYMBOL(__put_user_8);
+ EXPORT_SYMBOL(copy_user_generic);
+ EXPORT_SYMBOL(copy_from_user);
+ EXPORT_SYMBOL(copy_to_user);
++EXPORT_SYMBOL(__copy_from_user_inatomic);
+
+ EXPORT_SYMBOL(copy_page);
+ EXPORT_SYMBOL(clear_page);
+diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S
+index 962f3a6..70bebd3 100644
+--- a/arch/x86_64/lib/copy_user.S
++++ b/arch/x86_64/lib/copy_user.S
+@@ -9,10 +9,29 @@
+
+ #define FIX_ALIGNMENT 1
+
+- #include <asm/current.h>
+- #include <asm/asm-offsets.h>
+- #include <asm/thread_info.h>
+- #include <asm/cpufeature.h>
++#include <asm/current.h>
++#include <asm/asm-offsets.h>
++#include <asm/thread_info.h>
++#include <asm/cpufeature.h>
++
++ .macro ALTERNATIVE_JUMP feature,orig,alt
++0:
++ .byte 0xe9 /* 32bit jump */
++ .long \orig-1f /* by default jump to orig */
++1:
++ .section .altinstr_replacement,"ax"
++2: .byte 0xe9 /* near jump with 32bit immediate */
++ .long \alt-1b /* offset */ /* or alternatively to alt */
++ .previous
++ .section .altinstructions,"a"
++ .align 8
++ .quad 0b
++ .quad 2b
++ .byte \feature /* when feature is set */
++ .byte 5
++ .byte 5
++ .previous
++ .endm
+
+ /* Standard copy_to_user with segment limit checking */
+ ENTRY(copy_to_user)
+@@ -23,25 +42,21 @@ ENTRY(copy_to_user)
+ jc bad_to_user
+ cmpq threadinfo_addr_limit(%rax),%rcx
+ jae bad_to_user
+-2:
+- .byte 0xe9 /* 32bit jump */
+- .long .Lcug-1f
+-1:
++ xorl %eax,%eax /* clear zero flag */
++ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+-ENDPROC(copy_to_user)
+
+- .section .altinstr_replacement,"ax"
+-3: .byte 0xe9 /* replacement jmp with 32 bit immediate */
+- .long copy_user_generic_c-1b /* offset */
+- .previous
+- .section .altinstructions,"a"
+- .align 8
+- .quad 2b
+- .quad 3b
+- .byte X86_FEATURE_REP_GOOD
+- .byte 5
+- .byte 5
+- .previous
++ENTRY(copy_user_generic)
++ CFI_STARTPROC
++ movl $1,%ecx /* set zero flag */
++ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
++ CFI_ENDPROC
++
++ENTRY(__copy_from_user_inatomic)
++ CFI_STARTPROC
++ xorl %ecx,%ecx /* clear zero flag */
++ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
++ CFI_ENDPROC
+
+ /* Standard copy_from_user with segment limit checking */
+ ENTRY(copy_from_user)
+@@ -52,7 +67,8 @@ ENTRY(copy_from_user)
+ jc bad_from_user
+ cmpq threadinfo_addr_limit(%rax),%rcx
+ jae bad_from_user
+- /* FALL THROUGH to copy_user_generic */
++ movl $1,%ecx /* set zero flag */
++ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+ ENDPROC(copy_from_user)
+
+@@ -73,37 +89,26 @@ END(bad_from_user)
+
+
+ /*
+- * copy_user_generic - memory copy with exception handling.
++ * copy_user_generic_unrolled - memory copy with exception handling.
++ * This version is for CPUs like P4 that don't have efficient micro code for rep movsq
+ *
+ * Input:
+ * rdi destination
+ * rsi source
+ * rdx count
++ * ecx zero flag -- if true zero destination on error
+ *
+ * Output:
+ * eax uncopied bytes or 0 if successful.
+ */
+-ENTRY(copy_user_generic)
++ENTRY(copy_user_generic_unrolled)
+ CFI_STARTPROC
+- .byte 0x66,0x66,0x90 /* 5 byte nop for replacement jump */
+- .byte 0x66,0x90
+-1:
+- .section .altinstr_replacement,"ax"
+-2: .byte 0xe9 /* near jump with 32bit immediate */
+- .long copy_user_generic_c-1b /* offset */
+- .previous
+- .section .altinstructions,"a"
+- .align 8
+- .quad copy_user_generic
+- .quad 2b
+- .byte X86_FEATURE_REP_GOOD
+- .byte 5
+- .byte 5
+- .previous
+-.Lcug:
+ pushq %rbx
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rbx, 0
++ pushq %rcx
++ CFI_ADJUST_CFA_OFFSET 8
++ CFI_REL_OFFSET rcx, 0
+ xorl %eax,%eax /*zero for the exception handler */
+
+ #ifdef FIX_ALIGNMENT
+@@ -179,6 +184,9 @@ ENTRY(copy_user_generic)
+
+ CFI_REMEMBER_STATE
+ .Lende:
++ popq %rcx
++ CFI_ADJUST_CFA_OFFSET -8
++ CFI_RESTORE rcx
+ popq %rbx
+ CFI_ADJUST_CFA_OFFSET -8
+ CFI_RESTORE rbx
+@@ -265,6 +273,8 @@ ENTRY(copy_user_generic)
+ addl %ecx,%edx
+ /* edx: bytes to zero, rdi: dest, eax:zero */
+ .Lzero_rest:
++ cmpl $0,(%rsp)
++ jz .Le_zero
+ movq %rdx,%rcx
+ .Le_byte:
+ xorl %eax,%eax
+@@ -286,6 +296,7 @@ ENDPROC(copy_user_generic)
+ /* rdi destination
+ * rsi source
+ * rdx count
++ * ecx zero flag
+ *
+ * Output:
+ * eax uncopied bytes or 0 if successfull.
+@@ -296,25 +307,48 @@ ENDPROC(copy_user_generic)
+ * And more would be dangerous because both Intel and AMD have
+ * errata with rep movsq > 4GB. If someone feels the need to fix
+ * this please consider this.
+- */
+-copy_user_generic_c:
++ */
++ENTRY(copy_user_generic_string)
+ CFI_STARTPROC
++ movl %ecx,%r8d /* save zero flag */
+ movl %edx,%ecx
+ shrl $3,%ecx
+ andl $7,%edx
++ jz 10f
+ 1: rep
+ movsq
+ movl %edx,%ecx
+ 2: rep
+ movsb
+-4: movl %ecx,%eax
++9: movl %ecx,%eax
+ ret
+-3: lea (%rdx,%rcx,8),%rax
++
++ /* multiple of 8 byte */
++10: rep
++ movsq
++ xor %eax,%eax
+ ret
++
++ /* exception handling */
++3: lea (%rdx,%rcx,8),%rax /* exception on quad loop */
++ jmp 6f
++5: movl %ecx,%eax /* exception on byte loop */
++ /* eax: left over bytes */
++6: testl %r8d,%r8d /* zero flag set? */
++ jz 7f
++ movl %eax,%ecx /* initialize x86 loop counter */
++ push %rax
++ xorl %eax,%eax
++8: rep
++ stosb /* zero the rest */
++11: pop %rax
++7: ret
+ CFI_ENDPROC
+ END(copy_user_generic_c)
+
+ .section __ex_table,"a"
+ .quad 1b,3b
+- .quad 2b,4b
++ .quad 2b,5b
++ .quad 8b,11b
++ .quad 10b,3b
+ .previous
+diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
+index 1e1fa00..bc68120 100644
+--- a/include/asm-x86_64/uaccess.h
++++ b/include/asm-x86_64/uaccess.h
+@@ -238,6 +238,7 @@ do { \
+
+ /* Handles exceptions in both to and from, but doesn't do access_ok */
+ extern unsigned long copy_user_generic(void *to, const void *from, unsigned len);
++extern unsigned long copy_user_generic_dontzero(void *to, const void *from, unsigned len);
+
+ extern unsigned long copy_to_user(void __user *to, const void *from, unsigned len);
+ extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len);
+@@ -303,7 +304,6 @@ static __always_inline int __copy_to_user(void __user *dst, const void *src, uns
+ }
+ }
+
+-
+ static __always_inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
+ {
+ int ret = 0;
+@@ -352,7 +352,7 @@ long strlen_user(const char __user *str);
+ unsigned long clear_user(void __user *mem, unsigned long len);
+ unsigned long __clear_user(void __user *mem, unsigned long len);
+
+-#define __copy_to_user_inatomic __copy_to_user
+-#define __copy_from_user_inatomic __copy_from_user
++extern long __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size);
++#define __copy_to_user_inatomic copy_user_generic
+
+ #endif /* __X86_64_UACCESS_H */
diff --git a/trunk/2.6.18/30080_tty-fix-for-tty-operations-bugs.patch b/trunk/2.6.18/30080_tty-fix-for-tty-operations-bugs.patch
new file mode 100644
index 0000000..5c42b38
--- /dev/null
+++ b/trunk/2.6.18/30080_tty-fix-for-tty-operations-bugs.patch
@@ -0,0 +1,183 @@
+From alan@lxorguk.ukuu.org.uk Fri Jun 27 07:39:26 2008
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Date: Fri, 27 Jun 2008 15:21:55 +0100
+Subject: TTY: fix for tty operations bugs
+To: greg@kroah.com
+Message-ID: <20080627152155.50f0ebae@lxorguk.ukuu.org.uk>
+
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+This is fixed with the recent tty operations rewrite in mainline in a
+different way, this is a selective backport of the relevant portions to
+the -stable tree.
+
+Signed-off-by: Alan Cox <alan@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+
+Adjusted to apply to Debian's 2.6.18 by dann frazier <dannf@debian.org>
+
+diff -urpN linux-source-2.6.18.orig/drivers/net/hamradio/6pack.c linux-source-2.6.18/drivers/net/hamradio/6pack.c
+--- linux-source-2.6.18.orig/drivers/net/hamradio/6pack.c 2008-06-16 16:25:20.000000000 -0600
++++ linux-source-2.6.18/drivers/net/hamradio/6pack.c 2008-07-02 02:45:08.000000000 -0600
+@@ -601,6 +601,8 @@ static int sixpack_open(struct tty_struc
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
++ if (!tty->driver->write)
++ return -EOPNOTSUPP;
+
+ dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
+ if (!dev) {
+diff -urpN linux-source-2.6.18.orig/drivers/net/hamradio/mkiss.c linux-source-2.6.18/drivers/net/hamradio/mkiss.c
+--- linux-source-2.6.18.orig/drivers/net/hamradio/mkiss.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/drivers/net/hamradio/mkiss.c 2008-07-02 02:45:08.000000000 -0600
+@@ -530,6 +530,7 @@ static void ax_encaps(struct net_device
+ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+ struct mkiss *ax = netdev_priv(dev);
++ int cib = 0;
+
+ if (!netif_running(dev)) {
+ printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
+@@ -545,10 +546,11 @@ static int ax_xmit(struct sk_buff *skb,
+ /* 20 sec timeout not reached */
+ return 1;
+ }
++ if (ax->tty->driver->chars_in_buffer)
++ cib = ax->tty->driver->chars_in_buffer(ax->tty);
+
+ printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
+- (ax->tty->driver->chars_in_buffer(ax->tty) || ax->xleft) ?
+- "bad line quality" : "driver error");
++ cib || ax->xleft ? "bad line quality" : "driver error");
+
+ ax->xleft = 0;
+ clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
+@@ -736,6 +738,8 @@ static int mkiss_open(struct tty_struct
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
++ if (!tty->driver->write)
++ return -EOPNOTSUPP;
+
+ dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
+ if (!dev) {
+diff -urpN linux-source-2.6.18.orig/drivers/net/irda/irtty-sir.c linux-source-2.6.18/drivers/net/irda/irtty-sir.c
+--- linux-source-2.6.18.orig/drivers/net/irda/irtty-sir.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/drivers/net/irda/irtty-sir.c 2008-07-02 02:45:08.000000000 -0600
+@@ -64,7 +64,9 @@ static int irtty_chars_in_buffer(struct
+ IRDA_ASSERT(priv != NULL, return -1;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
+
+- return priv->tty->driver->chars_in_buffer(priv->tty);
++ if (priv->tty->driver->chars_in_buffer)
++ return priv->tty->driver->chars_in_buffer(priv->tty);
++ return 0;
+ }
+
+ /* Wait (sleep) until underlaying hardware finished transmission
+diff -urpN linux-source-2.6.18.orig/drivers/net/ppp_async.c linux-source-2.6.18/drivers/net/ppp_async.c
+--- linux-source-2.6.18.orig/drivers/net/ppp_async.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/drivers/net/ppp_async.c 2008-07-02 02:45:08.000000000 -0600
+@@ -158,6 +158,9 @@ ppp_asynctty_open(struct tty_struct *tty
+ struct asyncppp *ap;
+ int err;
+
++ if (!tty->driver->write)
++ return -EOPNOTSUPP;
++
+ err = -ENOMEM;
+ ap = kmalloc(sizeof(*ap), GFP_KERNEL);
+ if (ap == 0)
+diff -urpN linux-source-2.6.18.orig/drivers/net/ppp_synctty.c linux-source-2.6.18/drivers/net/ppp_synctty.c
+--- linux-source-2.6.18.orig/drivers/net/ppp_synctty.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/drivers/net/ppp_synctty.c 2008-07-02 02:49:36.000000000 -0600
+@@ -207,6 +207,9 @@ ppp_sync_open(struct tty_struct *tty)
+ struct syncppp *ap;
+ int err;
+
++ if (!tty->driver->write)
++ return -EOPNOTSUPP;
++
+ ap = kmalloc(sizeof(*ap), GFP_KERNEL);
+ err = -ENOMEM;
+ if (ap == 0)
+diff -urpN linux-source-2.6.18.orig/drivers/net/slip.c linux-source-2.6.18/drivers/net/slip.c
+--- linux-source-2.6.18.orig/drivers/net/slip.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/drivers/net/slip.c 2008-07-02 02:48:57.000000000 -0600
+@@ -463,9 +463,14 @@ static void sl_tx_timeout(struct net_dev
+ /* 20 sec timeout not reached */
+ goto out;
+ }
+- printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+- (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
+- "bad line quality" : "driver error");
++ {
++ int cib = 0;
++ if (sl->tty->driver->chars_in_buffer)
++ cib = sl->tty->driver->chars_in_buffer(sl->tty);
++ printk(KERN_WARNING "%s: transmit timed out, %s?\n",
++ dev->name, (cib || sl->xleft) ?
++ "bad line quality" : "driver error");
++ }
+ sl->xleft = 0;
+ sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ sl_unlock(sl);
+@@ -836,6 +841,8 @@ static int slip_open(struct tty_struct *
+
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
++ if (!tty->driver->write)
++ return -EOPNOTSUPP;
+
+ /* RTnetlink lock is misused here to serialize concurrent
+ opens of slip channels. There are better ways, but it is
+diff -urpN linux-source-2.6.18.orig/drivers/net/wan/x25_asy.c linux-source-2.6.18/drivers/net/wan/x25_asy.c
+--- linux-source-2.6.18.orig/drivers/net/wan/x25_asy.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/drivers/net/wan/x25_asy.c 2008-07-02 02:45:08.000000000 -0600
+@@ -283,6 +283,10 @@ static void x25_asy_write_wakeup(struct
+ static void x25_asy_timeout(struct net_device *dev)
+ {
+ struct x25_asy *sl = (struct x25_asy*)(dev->priv);
++ int cib = 0;
++
++ if (sl->tty->driver->chars_in_buffer)
++ cib = sl->tty->driver->chars_in_buffer(sl->tty);
+
+ spin_lock(&sl->lock);
+ if (netif_queue_stopped(dev)) {
+@@ -290,8 +294,7 @@ static void x25_asy_timeout(struct net_d
+ * 14 Oct 1994 Dmitry Gorodchanin.
+ */
+ printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+- (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
+- "bad line quality" : "driver error");
++ (cib || sl->xleft) ? "bad line quality" : "driver error");
+ sl->xleft = 0;
+ sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ x25_asy_unlock(sl);
+@@ -561,6 +564,9 @@ static int x25_asy_open_tty(struct tty_s
+ return -EEXIST;
+ }
+
++ if (!tty->driver->write)
++ return -EOPNOTSUPP;
++
+ /* OK. Find a free X.25 channel to use. */
+ if ((sl = x25_asy_alloc()) == NULL) {
+ return -ENFILE;
+diff -urpN linux-source-2.6.18.orig/drivers/net/wireless/strip.c linux-source-2.6.18/drivers/net/wireless/strip.c
+--- linux-source-2.6.18.orig/drivers/net/wireless/strip.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/drivers/net/wireless/strip.c 2008-07-02 02:45:08.000000000 -0600
+@@ -801,7 +801,8 @@ static void set_baud(struct tty_struct *
+ struct termios old_termios = *(tty->termios);
+ tty->termios->c_cflag &= ~CBAUD; /* Clear the old baud setting */
+ tty->termios->c_cflag |= baudcode; /* Set the new baud setting */
+- tty->driver->set_termios(tty, &old_termios);
++ if (tty->driver->set_termios)
++ tty->driver->set_termios(tty, &old_termios);
+ }
+
+ /*
diff --git a/trunk/2.6.18/30081_check-privileges-before-setting-mount-propagation.patch b/trunk/2.6.18/30081_check-privileges-before-setting-mount-propagation.patch
new file mode 100644
index 0000000..b08c50e
--- /dev/null
+++ b/trunk/2.6.18/30081_check-privileges-before-setting-mount-propagation.patch
@@ -0,0 +1,28 @@
+commit ee6f958291e2a768fd727e7a67badfff0b67711a
+Author: Miklos Szeredi <mszeredi@suse.cz>
+Date: Tue May 8 00:30:40 2007 -0700
+
+ check privileges before setting mount propagation
+
+ There's a missing check for CAP_SYS_ADMIN in do_change_type().
+
+ Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+ Cc: Al Viro <viro@zeniv.linux.org.uk>
+ Cc: Christoph Hellwig <hch@lst.de>
+ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+ Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 72bb106..b696e3a 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -886,6 +886,9 @@ static int do_change_type(struct nameidata *nd, int flag)
+ int recurse = flag & MS_REC;
+ int type = flag & ~MS_REC;
+
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
+ if (nd->dentry != nd->mnt->mnt_root)
+ return -EINVAL;
+
diff --git a/trunk/2.6.18/30082a_x86-add-copy_user_handle_tail.patch b/trunk/2.6.18/30082a_x86-add-copy_user_handle_tail.patch
new file mode 100644
index 0000000..27cfb86
--- /dev/null
+++ b/trunk/2.6.18/30082a_x86-add-copy_user_handle_tail.patch
@@ -0,0 +1,56 @@
+commit 1129585a08baf58582c0da91e572cb29e3179acf
+Author: Vitaly Mayatskikh <v.mayatskih@gmail.com>
+Date: Wed Jul 2 15:48:21 2008 +0200
+
+ x86: introduce copy_user_handle_tail() routine
+
+ Introduce generic C routine for handling necessary tail operations after
+ protection fault in copy_*_user on x86.
+
+ Signed-off-by: Vitaly Mayatskikh <v.mayatskih@gmail.com>
+ Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
+ Signed-off-by: Ingo Molnar <mingo@elte.hu>
+
+Backported to Debian's 2.6.18 by dann frazier <dannf@debian.org>
+
+diff -urpN linux-source-2.6.18.orig/arch/x86_64/lib/usercopy.c linux-source-2.6.18/arch/x86_64/lib/usercopy.c
+--- linux-source-2.6.18.orig/arch/x86_64/lib/usercopy.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/arch/x86_64/lib/usercopy.c 2008-07-16 02:39:08.000000000 -0600
+@@ -164,3 +164,26 @@ unsigned long copy_in_user(void __user *
+ }
+ EXPORT_SYMBOL(copy_in_user);
+
++/*
++ * Try to copy last bytes and clear the rest if needed.
++ * Since protection fault in copy_from/to_user is not a normal situation,
++ * it is not necessary to optimize tail handling.
++ */
++unsigned long
++copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest)
++{
++ char c;
++ unsigned zero_len;
++
++ for (; len; --len) {
++ if (__get_user_nocheck(c, from++, sizeof(char)))
++ break;
++ if (__put_user_nocheck(c, to++, sizeof(char)))
++ break;
++ }
++
++ for (c = 0, zero_len = len; zerorest && zero_len; --zero_len)
++ if (__put_user_nocheck(c, to++, sizeof(char)))
++ break;
++ return len;
++}
+diff -urpN linux-source-2.6.18.orig/include/asm-x86_64/uaccess.h linux-source-2.6.18/include/asm-x86_64/uaccess.h
+--- linux-source-2.6.18.orig/include/asm-x86_64/uaccess.h 2008-07-16 00:01:24.000000000 -0600
++++ linux-source-2.6.18/include/asm-x86_64/uaccess.h 2008-07-16 02:39:15.000000000 -0600
+@@ -355,4 +355,7 @@ unsigned long __clear_user(void __user *
+ extern long __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size);
+ #define __copy_to_user_inatomic copy_user_generic
+
++unsigned long
++copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest);
++
+ #endif /* __X86_64_UACCESS_H */
diff --git a/trunk/2.6.18/30082b_x86-fix-copy_user.patch b/trunk/2.6.18/30082b_x86-fix-copy_user.patch
new file mode 100644
index 0000000..f0b7a07
--- /dev/null
+++ b/trunk/2.6.18/30082b_x86-fix-copy_user.patch
@@ -0,0 +1,537 @@
+commit ad2fc2cd925300b8127cf682f5a1c7511ae9dd27
+Author: Vitaly Mayatskikh <v.mayatskih@gmail.com>
+Date: Wed Jul 2 15:53:13 2008 +0200
+
+ x86: fix copy_user on x86
+
+ Switch copy_user_generic_string(), copy_user_generic_unrolled() and
+ __copy_user_nocache() from custom tail handlers to generic
+ copy_user_tail_handle().
+
+ Signed-off-by: Vitaly Mayatskikh <v.mayatskih@gmail.com>
+ Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
+ Signed-off-by: Ingo Molnar <mingo@elte.hu>
+
+Backported to Debian's 2.6.18 by dann frazier <dannf@debian.org>
+
+diff -urpN linux-source-2.6.18.orig/arch/x86_64/lib/copy_user.S linux-source-2.6.18/arch/x86_64/lib/copy_user.S
+--- linux-source-2.6.18.orig/arch/x86_64/lib/copy_user.S 2008-07-15 23:01:24.000000000 -0700
++++ linux-source-2.6.18/arch/x86_64/lib/copy_user.S 2008-07-15 23:33:23.000000000 -0700
+@@ -1,8 +1,10 @@
+-/* Copyright 2002 Andi Kleen, SuSE Labs.
++/*
++ * Copyright 2008 Vitaly Mayatskikh <vmayatsk@redhat.com>
++ * Copyright 2002 Andi Kleen, SuSE Labs.
+ * Subject to the GNU Public License v2.
+- *
+- * Functions to copy from and to user space.
+- */
++ *
++ * Functions to copy from and to user space.
++ */
+
+ #include <linux/linkage.h>
+ #include <asm/dwarf2.h>
+@@ -20,60 +22,88 @@
+ .long \orig-1f /* by default jump to orig */
+ 1:
+ .section .altinstr_replacement,"ax"
+-2: .byte 0xe9 /* near jump with 32bit immediate */
++2: .byte 0xe9 /* near jump with 32bit immediate */
+ .long \alt-1b /* offset */ /* or alternatively to alt */
+ .previous
+ .section .altinstructions,"a"
+ .align 8
+ .quad 0b
+ .quad 2b
+- .byte \feature /* when feature is set */
++ .byte \feature /* when feature is set */
+ .byte 5
+ .byte 5
+ .previous
+ .endm
+
+-/* Standard copy_to_user with segment limit checking */
++ .macro ALIGN_DESTINATION
++#ifdef FIX_ALIGNMENT
++ /* check for bad alignment of destination */
++ movl %edi,%ecx
++ andl $7,%ecx
++ jz 102f /* already aligned */
++ subl $8,%ecx
++ negl %ecx
++ subl %ecx,%edx
++100: movb (%rsi),%al
++101: movb %al,(%rdi)
++ incq %rsi
++ incq %rdi
++ decl %ecx
++ jnz 100b
++102:
++ .section .fixup,"ax"
++103: addl %r8d,%edx /* ecx is zerorest also */
++ jmp copy_user_handle_tail
++ .previous
++
++ .section __ex_table,"a"
++ .align 8
++ .quad 100b,103b
++ .quad 101b,103b
++ .previous
++#endif
++ .endm
++
++/* Standard copy_to_user with segment limit checking */
+ ENTRY(copy_to_user)
+ CFI_STARTPROC
+ GET_THREAD_INFO(%rax)
+ movq %rdi,%rcx
+ addq %rdx,%rcx
+- jc bad_to_user
+- cmpq threadinfo_addr_limit(%rax),%rcx
++ jc bad_to_user
++ cmpq threadinfo_addr_limit(%rax),%rcx
+ jae bad_to_user
+- xorl %eax,%eax /* clear zero flag */
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+
+-ENTRY(copy_user_generic)
++/* Standard copy_from_user with segment limit checking */
++ENTRY(copy_from_user)
+ CFI_STARTPROC
+- movl $1,%ecx /* set zero flag */
++ GET_THREAD_INFO(%rax)
++ movq %rsi,%rcx
++ addq %rdx,%rcx
++ jc bad_from_user
++ cmpq threadinfo_addr_limit(%rax),%rcx
++ jae bad_from_user
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
++ENDPROC(copy_from_user)
+
+-ENTRY(__copy_from_user_inatomic)
++ENTRY(copy_user_generic)
+ CFI_STARTPROC
+- xorl %ecx,%ecx /* clear zero flag */
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
++ENDPROC(copy_user_generic)
+
+-/* Standard copy_from_user with segment limit checking */
+-ENTRY(copy_from_user)
++ENTRY(__copy_from_user_inatomic)
+ CFI_STARTPROC
+- GET_THREAD_INFO(%rax)
+- movq %rsi,%rcx
+- addq %rdx,%rcx
+- jc bad_from_user
+- cmpq threadinfo_addr_limit(%rax),%rcx
+- jae bad_from_user
+- movl $1,%ecx /* set zero flag */
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+-ENDPROC(copy_from_user)
+-
++ENDPROC(__copy_from_user_inatomic)
++
+ .section .fixup,"ax"
+ /* must zero dest */
++ENTRY(bad_from_user)
+ bad_from_user:
+ CFI_STARTPROC
+ movl %edx,%ecx
+@@ -81,274 +111,158 @@ bad_from_user:
+ rep
+ stosb
+ bad_to_user:
+- movl %edx,%eax
++ movl %edx,%eax
+ ret
+ CFI_ENDPROC
+-END(bad_from_user)
++ENDPROC(bad_from_user)
+ .previous
+-
+-
++
+ /*
+ * copy_user_generic_unrolled - memory copy with exception handling.
+- * This version is for CPUs like P4 that don't have efficient micro code for rep movsq
+- *
+- * Input:
++ * This version is for CPUs like P4 that don't have efficient micro
++ * code for rep movsq
++ *
++ * Input:
+ * rdi destination
+ * rsi source
+ * rdx count
+- * ecx zero flag -- if true zero destination on error
+ *
+- * Output:
+- * eax uncopied bytes or 0 if successful.
++ * Output:
++ * eax uncopied bytes or 0 if successfull.
+ */
+ ENTRY(copy_user_generic_unrolled)
+ CFI_STARTPROC
+- pushq %rbx
+- CFI_ADJUST_CFA_OFFSET 8
+- CFI_REL_OFFSET rbx, 0
+- pushq %rcx
+- CFI_ADJUST_CFA_OFFSET 8
+- CFI_REL_OFFSET rcx, 0
+- xorl %eax,%eax /*zero for the exception handler */
+-
+-#ifdef FIX_ALIGNMENT
+- /* check for bad alignment of destination */
+- movl %edi,%ecx
+- andl $7,%ecx
+- jnz .Lbad_alignment
+-.Lafter_bad_alignment:
+-#endif
+-
+- movq %rdx,%rcx
+-
+- movl $64,%ebx
+- shrq $6,%rdx
+- decq %rdx
+- js .Lhandle_tail
+-
+- .p2align 4
+-.Lloop:
+-.Ls1: movq (%rsi),%r11
+-.Ls2: movq 1*8(%rsi),%r8
+-.Ls3: movq 2*8(%rsi),%r9
+-.Ls4: movq 3*8(%rsi),%r10
+-.Ld1: movq %r11,(%rdi)
+-.Ld2: movq %r8,1*8(%rdi)
+-.Ld3: movq %r9,2*8(%rdi)
+-.Ld4: movq %r10,3*8(%rdi)
+-
+-.Ls5: movq 4*8(%rsi),%r11
+-.Ls6: movq 5*8(%rsi),%r8
+-.Ls7: movq 6*8(%rsi),%r9
+-.Ls8: movq 7*8(%rsi),%r10
+-.Ld5: movq %r11,4*8(%rdi)
+-.Ld6: movq %r8,5*8(%rdi)
+-.Ld7: movq %r9,6*8(%rdi)
+-.Ld8: movq %r10,7*8(%rdi)
+-
+- decq %rdx
+-
++ cmpl $8,%edx
++ jb 20f /* less then 8 bytes, go to byte copy loop */
++ ALIGN_DESTINATION
++ movl %edx,%ecx
++ andl $63,%edx
++ shrl $6,%ecx
++ jz 17f
++1: movq (%rsi),%r8
++2: movq 1*8(%rsi),%r9
++3: movq 2*8(%rsi),%r10
++4: movq 3*8(%rsi),%r11
++5: movq %r8,(%rdi)
++6: movq %r9,1*8(%rdi)
++7: movq %r10,2*8(%rdi)
++8: movq %r11,3*8(%rdi)
++9: movq 4*8(%rsi),%r8
++10: movq 5*8(%rsi),%r9
++11: movq 6*8(%rsi),%r10
++12: movq 7*8(%rsi),%r11
++13: movq %r8,4*8(%rdi)
++14: movq %r9,5*8(%rdi)
++15: movq %r10,6*8(%rdi)
++16: movq %r11,7*8(%rdi)
+ leaq 64(%rsi),%rsi
+ leaq 64(%rdi),%rdi
+-
+- jns .Lloop
+-
+- .p2align 4
+-.Lhandle_tail:
+- movl %ecx,%edx
+- andl $63,%ecx
+- shrl $3,%ecx
+- jz .Lhandle_7
+- movl $8,%ebx
+- .p2align 4
+-.Lloop_8:
+-.Ls9: movq (%rsi),%r8
+-.Ld9: movq %r8,(%rdi)
+ decl %ecx
+- leaq 8(%rdi),%rdi
++ jnz 1b
++17: movl %edx,%ecx
++ andl $7,%edx
++ shrl $3,%ecx
++ jz 20f
++18: movq (%rsi),%r8
++19: movq %r8,(%rdi)
+ leaq 8(%rsi),%rsi
+- jnz .Lloop_8
+-
+-.Lhandle_7:
++ leaq 8(%rdi),%rdi
++ decl %ecx
++ jnz 18b
++20: andl %edx,%edx
++ jz 23f
+ movl %edx,%ecx
+- andl $7,%ecx
+- jz .Lende
+- .p2align 4
+-.Lloop_1:
+-.Ls10: movb (%rsi),%bl
+-.Ld10: movb %bl,(%rdi)
+- incq %rdi
++21: movb (%rsi),%al
++22: movb %al,(%rdi)
+ incq %rsi
++ incq %rdi
+ decl %ecx
+- jnz .Lloop_1
+-
+- CFI_REMEMBER_STATE
+-.Lende:
+- popq %rcx
+- CFI_ADJUST_CFA_OFFSET -8
+- CFI_RESTORE rcx
+- popq %rbx
+- CFI_ADJUST_CFA_OFFSET -8
+- CFI_RESTORE rbx
++ jnz 21b
++23: xor %eax,%eax
+ ret
+- CFI_RESTORE_STATE
+
+-#ifdef FIX_ALIGNMENT
+- /* align destination */
+- .p2align 4
+-.Lbad_alignment:
+- movl $8,%r9d
+- subl %ecx,%r9d
+- movl %r9d,%ecx
+- cmpq %r9,%rdx
+- jz .Lhandle_7
+- js .Lhandle_7
+-.Lalign_1:
+-.Ls11: movb (%rsi),%bl
+-.Ld11: movb %bl,(%rdi)
+- incq %rsi
+- incq %rdi
+- decl %ecx
+- jnz .Lalign_1
+- subq %r9,%rdx
+- jmp .Lafter_bad_alignment
+-#endif
++ .section .fixup,"ax"
++30: shll $6,%ecx
++ addl %ecx,%edx
++ jmp 60f
++40: lea (%rdx,%rcx,8),%rdx
++ jmp 60f
++50: movl %ecx,%edx
++60: jmp copy_user_handle_tail /* ecx is zerorest also */
++ .previous
+
+- /* table sorted by exception address */
+ .section __ex_table,"a"
+ .align 8
+- .quad .Ls1,.Ls1e
+- .quad .Ls2,.Ls2e
+- .quad .Ls3,.Ls3e
+- .quad .Ls4,.Ls4e
+- .quad .Ld1,.Ls1e
+- .quad .Ld2,.Ls2e
+- .quad .Ld3,.Ls3e
+- .quad .Ld4,.Ls4e
+- .quad .Ls5,.Ls5e
+- .quad .Ls6,.Ls6e
+- .quad .Ls7,.Ls7e
+- .quad .Ls8,.Ls8e
+- .quad .Ld5,.Ls5e
+- .quad .Ld6,.Ls6e
+- .quad .Ld7,.Ls7e
+- .quad .Ld8,.Ls8e
+- .quad .Ls9,.Le_quad
+- .quad .Ld9,.Le_quad
+- .quad .Ls10,.Le_byte
+- .quad .Ld10,.Le_byte
+-#ifdef FIX_ALIGNMENT
+- .quad .Ls11,.Lzero_rest
+- .quad .Ld11,.Lzero_rest
+-#endif
+- .quad .Le5,.Le_zero
++ .quad 1b,30b
++ .quad 2b,30b
++ .quad 3b,30b
++ .quad 4b,30b
++ .quad 5b,30b
++ .quad 6b,30b
++ .quad 7b,30b
++ .quad 8b,30b
++ .quad 9b,30b
++ .quad 10b,30b
++ .quad 11b,30b
++ .quad 12b,30b
++ .quad 13b,30b
++ .quad 14b,30b
++ .quad 15b,30b
++ .quad 16b,30b
++ .quad 18b,40b
++ .quad 19b,40b
++ .quad 21b,50b
++ .quad 22b,50b
+ .previous
+-
+- /* compute 64-offset for main loop. 8 bytes accuracy with error on the
+- pessimistic side. this is gross. it would be better to fix the
+- interface. */
+- /* eax: zero, ebx: 64 */
+-.Ls1e: addl $8,%eax
+-.Ls2e: addl $8,%eax
+-.Ls3e: addl $8,%eax
+-.Ls4e: addl $8,%eax
+-.Ls5e: addl $8,%eax
+-.Ls6e: addl $8,%eax
+-.Ls7e: addl $8,%eax
+-.Ls8e: addl $8,%eax
+- addq %rbx,%rdi /* +64 */
+- subq %rax,%rdi /* correct destination with computed offset */
+-
+- shlq $6,%rdx /* loop counter * 64 (stride length) */
+- addq %rax,%rdx /* add offset to loopcnt */
+- andl $63,%ecx /* remaining bytes */
+- addq %rcx,%rdx /* add them */
+- jmp .Lzero_rest
+-
+- /* exception on quad word loop in tail handling */
+- /* ecx: loopcnt/8, %edx: length, rdi: correct */
+-.Le_quad:
+- shll $3,%ecx
+- andl $7,%edx
+- addl %ecx,%edx
+- /* edx: bytes to zero, rdi: dest, eax:zero */
+-.Lzero_rest:
+- cmpl $0,(%rsp)
+- jz .Le_zero
+- movq %rdx,%rcx
+-.Le_byte:
+- xorl %eax,%eax
+-.Le5: rep
+- stosb
+- /* when there is another exception while zeroing the rest just return */
+-.Le_zero:
+- movq %rdx,%rax
+- jmp .Lende
+ CFI_ENDPROC
+-ENDPROC(copy_user_generic)
++ENDPROC(copy_user_generic_unrolled)
+
+-
+- /* Some CPUs run faster using the string copy instructions.
+- This is also a lot simpler. Use them when possible.
+- Patch in jmps to this code instead of copying it fully
+- to avoid unwanted aliasing in the exception tables. */
+-
+- /* rdi destination
+- * rsi source
+- * rdx count
+- * ecx zero flag
+- *
+- * Output:
+- * eax uncopied bytes or 0 if successfull.
+- *
+- * Only 4GB of copy is supported. This shouldn't be a problem
+- * because the kernel normally only writes from/to page sized chunks
+- * even if user space passed a longer buffer.
+- * And more would be dangerous because both Intel and AMD have
+- * errata with rep movsq > 4GB. If someone feels the need to fix
+- * this please consider this.
+- */
++/* Some CPUs run faster using the string copy instructions.
++ * This is also a lot simpler. Use them when possible.
++ *
++ * Only 4GB of copy is supported. This shouldn't be a problem
++ * because the kernel normally only writes from/to page sized chunks
++ * even if user space passed a longer buffer.
++ * And more would be dangerous because both Intel and AMD have
++ * errata with rep movsq > 4GB. If someone feels the need to fix
++ * this please consider this.
++ *
++ * Input:
++ * rdi destination
++ * rsi source
++ * rdx count
++ *
++ * Output:
++ * eax uncopied bytes or 0 if successful.
++ */
+ ENTRY(copy_user_generic_string)
+ CFI_STARTPROC
+- movl %ecx,%r8d /* save zero flag */
++ andl %edx,%edx
++ jz 4f
++ cmpl $8,%edx
++ jb 2f /* less than 8 bytes, go to byte copy loop */
++ ALIGN_DESTINATION
+ movl %edx,%ecx
+ shrl $3,%ecx
+- andl $7,%edx
+- jz 10f
+-1: rep
+- movsq
+- movl %edx,%ecx
+-2: rep
+- movsb
+-9: movl %ecx,%eax
+- ret
+-
+- /* multiple of 8 byte */
+-10: rep
++ andl $7,%edx
++1: rep
+ movsq
+- xor %eax,%eax
++2: movl %edx,%ecx
++3: rep
++ movsb
++4: xorl %eax,%eax
+ ret
+
+- /* exception handling */
+-3: lea (%rdx,%rcx,8),%rax /* exception on quad loop */
+- jmp 6f
+-5: movl %ecx,%eax /* exception on byte loop */
+- /* eax: left over bytes */
+-6: testl %r8d,%r8d /* zero flag set? */
+- jz 7f
+- movl %eax,%ecx /* initialize x86 loop counter */
+- push %rax
+- xorl %eax,%eax
+-8: rep
+- stosb /* zero the rest */
+-11: pop %rax
+-7: ret
+- CFI_ENDPROC
+-END(copy_user_generic_c)
++ .section .fixup,"ax"
++11: lea (%rdx,%rcx,8),%rcx
++12: movl %ecx,%edx /* ecx is zerorest also */
++ jmp copy_user_handle_tail
++ .previous
+
+ .section __ex_table,"a"
+- .quad 1b,3b
+- .quad 2b,5b
+- .quad 8b,11b
+- .quad 10b,3b
++ .align 8
++ .quad 1b,11b
++ .quad 3b,12b
+ .previous
++ CFI_ENDPROC
++ENDPROC(copy_user_generic_string)
diff --git a/trunk/2.6.18/30083_x86-wrong-register-was-used-in-align-macro.patch b/trunk/2.6.18/30083_x86-wrong-register-was-used-in-align-macro.patch
new file mode 100644
index 0000000..8ba33b0
--- /dev/null
+++ b/trunk/2.6.18/30083_x86-wrong-register-was-used-in-align-macro.patch
@@ -0,0 +1,29 @@
+commit afd962a9e8708c571c5c0c4a6d098f931742c229
+Author: Vitaly Mayatskikh <v.mayatskih@gmail.com>
+Date: Wed Jul 30 13:30:14 2008 +0200
+
+ x86: wrong register was used in align macro
+
+ New ALIGN_DESTINATION macro has sad typo: r8d register was used instead
+ of ecx in fixup section. This can be considered as a regression.
+
+ Register ecx was also wrongly loaded with value in r8d in
+ copy_user_nocache routine.
+
+ Signed-off-by: Vitaly Mayatskikh <v.mayatskih@gmail.com>
+ Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+Backported to Debian's 2.6.18 by dann frazier <dannf@debian.org>
+
+diff -urpN linux-source-2.6.18.orig/arch/x86_64/lib/copy_user.S linux-source-2.6.18/arch/x86_64/lib/copy_user.S
+--- linux-source-2.6.18.orig/arch/x86_64/lib/copy_user.S 2008-07-27 16:46:41.000000000 -0600
++++ linux-source-2.6.18/arch/x86_64/lib/copy_user.S 2008-08-12 00:13:09.000000000 -0600
+@@ -52,7 +52,7 @@
+ jnz 100b
+ 102:
+ .section .fixup,"ax"
+-103: addl %r8d,%edx /* ecx is zerorest also */
++103: addl %ecx,%edx /* ecx is zerorest also */
+ jmp copy_user_handle_tail
+ .previous
+
diff --git a/trunk/2.6.18/30084_cifs-fix-compiler-warning.patch b/trunk/2.6.18/30084_cifs-fix-compiler-warning.patch
new file mode 100644
index 0000000..098f634
--- /dev/null
+++ b/trunk/2.6.18/30084_cifs-fix-compiler-warning.patch
@@ -0,0 +1,21 @@
+commit 04e1e0cccade330ab3715ce59234f7e3b087e246
+Author: Jan Beulich <jbeulich@novell.com>
+Date: Tue Jul 22 13:04:18 2008 +0000
+
+ [CIFS] Fix compiler warning on 64-bit
+
+ Signed-off-by: Steve French <sfrench@us.ibm.com>
+
+diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
+index f58e41d..4276546 100644
+--- a/fs/cifs/asn1.c
++++ b/fs/cifs/asn1.c
+@@ -400,7 +400,7 @@ asn1_oid_decode(struct asn1_ctx *ctx,
+ size = eoc - ctx->pointer + 1;
+
+ /* first subid actually encodes first two subids */
+- if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
++ if (size < 2 || size > UINT_MAX/sizeof(unsigned long))
+ return 0;
+
+ *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
diff --git a/trunk/2.6.18/30085_netfilter-nf_nat_snmp_basic-fix-range-check.patch b/trunk/2.6.18/30085_netfilter-nf_nat_snmp_basic-fix-range-check.patch
new file mode 100644
index 0000000..3bf2353
--- /dev/null
+++ b/trunk/2.6.18/30085_netfilter-nf_nat_snmp_basic-fix-range-check.patch
@@ -0,0 +1,27 @@
+commit 252815b0cfe711001eff0327872209986b36d490
+Author: David Howells <dhowells@redhat.com>
+Date: Wed Jul 9 15:06:45 2008 -0700
+
+ netfilter: nf_nat_snmp_basic: fix a range check in NAT for SNMP
+
+ Fix a range check in netfilter IP NAT for SNMP to always use a big enough size
+ variable that the compiler won't moan about comparing it to ULONG_MAX/8 on a
+ 64-bit platform.
+
+ Signed-off-by: David Howells <dhowells@redhat.com>
+ Signed-off-by: Patrick McHardy <kaber@trash.net>
+ Signed-off-by: David S. Miller <davem@davemloft.net>
+
+diff -urpN linux-source-2.6.18.orig/net/ipv4/netfilter/ip_nat_snmp_basic.c linux-source-2.6.18/net/ipv4/netfilter/ip_nat_snmp_basic.c
+--- linux-source-2.6.18.orig/net/ipv4/netfilter/ip_nat_snmp_basic.c 2008-06-16 16:25:21.000000000 -0600
++++ linux-source-2.6.18/net/ipv4/netfilter/ip_nat_snmp_basic.c 2008-08-17 19:03:41.000000000 -0600
+@@ -442,8 +442,8 @@ static unsigned char asn1_oid_decode(str
+ unsigned int *len)
+ {
+ unsigned long subid;
+- unsigned int size;
+ unsigned long *optr;
++ size_t size;
+
+ size = eoc - ctx->pointer + 1;
+
diff --git a/trunk/2.6.18/30086_sound-ensure-device-number-is-valid-in-snd_seq_oss_synth_make_info.patch b/trunk/2.6.18/30086_sound-ensure-device-number-is-valid-in-snd_seq_oss_synth_make_info.patch
new file mode 100644
index 0000000..928c1ef
--- /dev/null
+++ b/trunk/2.6.18/30086_sound-ensure-device-number-is-valid-in-snd_seq_oss_synth_make_info.patch
@@ -0,0 +1,30 @@
+commit 82e68f7ffec3800425f2391c8c86277606860442
+Author: Willy Tarreau <w@1wt.eu>
+Date: Sat Aug 2 18:25:16 2008 +0200
+
+ sound: ensure device number is valid in snd_seq_oss_synth_make_info
+
+ snd_seq_oss_synth_make_info() incorrectly reports information
+ to userspace without first checking for the validity of the
+ device number, leading to possible information leak (CVE-2008-3272).
+
+ Reported-By: Tobias Klein <tk@trapkit.de>
+ Acked-and-tested-by: Takashi Iwai <tiwai@suse.de>
+ Cc: stable@kernel.org
+ Signed-off-by: Willy Tarreau <w@1wt.eu>
+ Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
+index 558dadb..e024e45 100644
+--- a/sound/core/seq/oss/seq_oss_synth.c
++++ b/sound/core/seq/oss/seq_oss_synth.c
+@@ -604,6 +604,9 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
+ {
+ struct seq_oss_synth *rec;
+
++ if (dev < 0 || dev >= dp->max_synthdev)
++ return -ENXIO;
++
+ if (dp->synths[dev].is_midi) {
+ struct midi_info minf;
+ snd_seq_oss_midi_make_info(dp, dp->synths[dev].midi_mapped, &minf);
diff --git a/trunk/2.6.18/30087_vfs-fix-lookup-on-deleted-directory.patch b/trunk/2.6.18/30087_vfs-fix-lookup-on-deleted-directory.patch
new file mode 100644
index 0000000..93605d0
--- /dev/null
+++ b/trunk/2.6.18/30087_vfs-fix-lookup-on-deleted-directory.patch
@@ -0,0 +1,71 @@
+commit d70b67c8bc72ee23b55381bd6a884f4796692f77
+Author: Miklos Szeredi <mszeredi@suse.cz>
+Date: Wed Jul 2 21:30:15 2008 +0200
+
+ [patch] vfs: fix lookup on deleted directory
+
+ Lookup can install a child dentry for a deleted directory. This keeps
+ the directory dentry alive, and the inode pinned in the cache and on
+ disk, even after all external references have gone away.
+
+ This isn't a big problem normally, since memory pressure or umount
+ will clear out the directory dentry and its children, releasing the
+ inode. But for UBIFS this causes problems because its orphan area can
+ overflow.
+
+ Fix this by returning ENOENT for all lookups on a S_DEAD directory
+ before creating a child dentry.
+
+ Thanks to Zoltan Sogor for noticing this while testing UBIFS, and
+ Artem for the excellent analysis of the problem and testing.
+
+ Reported-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+ Tested-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+ Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+ Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+
+Adjusted to apply to Debian's 2.6.18 by dann frazier <dannf@debian.org>
+
+diff -urpN linux-source-2.6.18.orig/fs/namei.c linux-source-2.6.18/fs/namei.c
+--- linux-source-2.6.18.orig/fs/namei.c 2008-06-16 16:25:21.000000000 -0600
++++ linux-source-2.6.18/fs/namei.c 2008-08-15 13:51:40.000000000 -0600
+@@ -465,7 +465,14 @@ static struct dentry * real_lookup(struc
+ */
+ result = d_lookup(parent, name);
+ if (!result) {
+- struct dentry * dentry = d_alloc(parent, name);
++ struct dentry *dentry;
++
++ /* Don't create child dentry for a dead directory. */
++ result = ERR_PTR(-ENOENT);
++ if (IS_DEADDIR(dir))
++ goto out_unlock;
++
++ dentry = d_alloc(parent, name);
+ result = ERR_PTR(-ENOMEM);
+ if (dentry) {
+ result = dir->i_op->lookup(dir, dentry, nd);
+@@ -474,6 +481,7 @@ static struct dentry * real_lookup(struc
+ else
+ result = dentry;
+ }
++out_unlock:
+ mutex_unlock(&dir->i_mutex);
+ return result;
+ }
+@@ -1248,7 +1256,14 @@ static struct dentry * __lookup_hash(str
+
+ dentry = cached_lookup(base, name, nd);
+ if (!dentry) {
+- struct dentry *new = d_alloc(base, name);
++ struct dentry *new;
++
++ /* Don't create child dentry for a dead directory. */
++ dentry = ERR_PTR(-ENOENT);
++ if (IS_DEADDIR(inode))
++ goto out;
++
++ new = d_alloc(base, name);
+ dentry = ERR_PTR(-ENOMEM);
+ if (!new)
+ goto out;